]> Pileus Git - ~andy/gtk/blob - gtk/gtkselection.c
Add gtk_selection_data_get_selection to retrieve the sealed struct field
[~andy/gtk] / gtk / gtkselection.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /* This file implements most of the work of the ICCCM selection protocol.
21  * The code was written after an intensive study of the equivalent part
22  * of John Ousterhout's Tk toolkit, and does many things in much the 
23  * same way.
24  *
25  * The one thing in the ICCCM that isn't fully supported here (or in Tk)
26  * is side effects targets. For these to be handled properly, MULTIPLE
27  * targets need to be done in the order specified. This cannot be
28  * guaranteed with the way we do things, since if we are doing INCR
29  * transfers, the order will depend on the timing of the requestor.
30  *
31  * By Owen Taylor <owt1@cornell.edu>          8/16/97
32  */
33
34 /* Terminology note: when not otherwise specified, the term "incr" below
35  * refers to the _sending_ part of the INCR protocol. The receiving
36  * portion is referred to just as "retrieval". (Terminology borrowed
37  * from Tk, because there is no good opposite to "retrieval" in English.
38  * "send" can't be made into a noun gracefully and we're already using
39  * "emission" for something else ....)
40  */
41
42 /* The MOTIF entry widget seems to ask for the TARGETS target, then
43    (regardless of the reply) ask for the TEXT target. It's slightly
44    possible though that it somehow thinks we are responding negatively
45    to the TARGETS request, though I don't really think so ... */
46
47 /*
48  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
49  * file for a list of people on the GTK+ Team.  See the ChangeLog
50  * files for a list of changes.  These files are distributed with
51  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
52  */
53
54 #include "config.h"
55 #include <stdarg.h>
56 #include <string.h>
57 #include "gdk.h"
58
59 #include "gtkmain.h"
60 #include "gtkselection.h"
61 #include "gtktextbufferrichtext.h"
62 #include "gtkintl.h"
63 #include "gdk-pixbuf/gdk-pixbuf.h"
64
65 #ifdef GDK_WINDOWING_X11
66 #include "x11/gdkx.h"
67 #endif
68
69 #ifdef GDK_WINDOWING_WIN32
70 #include "win32/gdkwin32.h"
71 #endif
72
73 #include "gtkalias.h"
74
75 #undef DEBUG_SELECTION
76
77 /* Maximum size of a sent chunk, in bytes. Also the default size of
78    our buffers */
79 #ifdef GDK_WINDOWING_X11
80 #define GTK_SELECTION_MAX_SIZE(display)                                 \
81   MIN(262144,                                                           \
82       XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0     \
83        ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100         \
84        : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
85 #else
86 /* No chunks on Win32 */
87 #define GTK_SELECTION_MAX_SIZE(display) G_MAXINT
88 #endif
89
90 #define IDLE_ABORT_TIME 30
91
92 enum {
93   INCR,
94   MULTIPLE,
95   TARGETS,
96   TIMESTAMP,
97   LAST_ATOM
98 };
99
100 typedef struct _GtkSelectionInfo GtkSelectionInfo;
101 typedef struct _GtkIncrConversion GtkIncrConversion;
102 typedef struct _GtkIncrInfo GtkIncrInfo;
103 typedef struct _GtkRetrievalInfo GtkRetrievalInfo;
104
105 struct _GtkSelectionInfo
106 {
107   GdkAtom        selection;
108   GtkWidget     *widget;        /* widget that owns selection */
109   guint32        time;          /* time used to acquire selection */
110   GdkDisplay    *display;       /* needed in gtk_selection_remove_all */    
111 };
112
113 struct _GtkIncrConversion 
114 {
115   GdkAtom           target;     /* Requested target */
116   GdkAtom           property;   /* Property to store in */
117   GtkSelectionData  data;       /* The data being supplied */
118   gint              offset;     /* Current offset in sent selection.
119                                  *  -1 => All done
120                                  *  -2 => Only the final (empty) portion
121                                  *        left to send */
122 };
123
124 struct _GtkIncrInfo
125 {
126   GdkWindow *requestor;         /* Requestor window - we create a GdkWindow
127                                    so we can receive events */
128   GdkAtom    selection;         /* Selection we're sending */
129   
130   GtkIncrConversion *conversions; /* Information about requested conversions -
131                                    * With MULTIPLE requests (benighted 1980's
132                                    * hardware idea), there can be more than
133                                    * one */
134   gint num_conversions;
135   gint num_incrs;               /* number of remaining INCR style transactions */
136   guint32 idle_time;
137 };
138
139
140 struct _GtkRetrievalInfo
141 {
142   GtkWidget *widget;
143   GdkAtom selection;            /* Selection being retrieved. */
144   GdkAtom target;               /* Form of selection that we requested */
145   guint32 idle_time;            /* Number of seconds since we last heard
146                                    from selection owner */
147   guchar   *buffer;             /* Buffer in which to accumulate results */
148   gint     offset;              /* Current offset in buffer, -1 indicates
149                                    not yet started */
150   guint32 notify_time;          /* Timestamp from SelectionNotify */
151 };
152
153 /* Local Functions */
154 static void gtk_selection_init              (void);
155 static gboolean gtk_selection_incr_timeout      (GtkIncrInfo      *info);
156 static gboolean gtk_selection_retrieval_timeout (GtkRetrievalInfo *info);
157 static void gtk_selection_retrieval_report  (GtkRetrievalInfo *info,
158                                              GdkAtom           type,
159                                              gint              format,
160                                              guchar           *buffer,
161                                              gint              length,
162                                              guint32           time);
163 static void gtk_selection_invoke_handler    (GtkWidget        *widget,
164                                              GtkSelectionData *data,
165                                              guint             time);
166 static void gtk_selection_default_handler   (GtkWidget        *widget,
167                                              GtkSelectionData *data);
168 static int  gtk_selection_bytes_per_item    (gint              format);
169
170 /* Local Data */
171 static gint initialize = TRUE;
172 static GList *current_retrievals = NULL;
173 static GList *current_incrs = NULL;
174 static GList *current_selections = NULL;
175
176 static GdkAtom gtk_selection_atoms[LAST_ATOM];
177 static const char gtk_selection_handler_key[] = "gtk-selection-handlers";
178
179 /****************
180  * Target Lists *
181  ****************/
182
183 /*
184  * Target lists
185  */
186
187
188 /**
189  * gtk_target_list_new:
190  * @targets: Pointer to an array of #GtkTargetEntry
191  * @ntargets:  number of entries in @targets.
192  * 
193  * Creates a new #GtkTargetList from an array of #GtkTargetEntry.
194  * 
195  * Return value: the new #GtkTargetList.
196  **/
197 GtkTargetList *
198 gtk_target_list_new (const GtkTargetEntry *targets,
199                      guint                 ntargets)
200 {
201   GtkTargetList *result = g_slice_new (GtkTargetList);
202   result->list = NULL;
203   result->ref_count = 1;
204
205   if (targets)
206     gtk_target_list_add_table (result, targets, ntargets);
207   
208   return result;
209 }
210
211 /**
212  * gtk_target_list_ref:
213  * @list:  a #GtkTargetList
214  * 
215  * Increases the reference count of a #GtkTargetList by one.
216  *
217  * Return value: the passed in #GtkTargetList.
218  **/
219 GtkTargetList *
220 gtk_target_list_ref (GtkTargetList *list)
221 {
222   g_return_val_if_fail (list != NULL, NULL);
223
224   list->ref_count++;
225
226   return list;
227 }
228
229 /**
230  * gtk_target_list_unref:
231  * @list: a #GtkTargetList
232  * 
233  * Decreases the reference count of a #GtkTargetList by one.
234  * If the resulting reference count is zero, frees the list.
235  **/
236 void               
237 gtk_target_list_unref (GtkTargetList *list)
238 {
239   g_return_if_fail (list != NULL);
240   g_return_if_fail (list->ref_count > 0);
241
242   list->ref_count--;
243   if (list->ref_count == 0)
244     {
245       GList *tmp_list = list->list;
246       while (tmp_list)
247         {
248           GtkTargetPair *pair = tmp_list->data;
249           g_slice_free (GtkTargetPair, pair);
250
251           tmp_list = tmp_list->next;
252         }
253       
254       g_list_free (list->list);
255       g_slice_free (GtkTargetList, list);
256     }
257 }
258
259 /**
260  * gtk_target_list_add:
261  * @list:  a #GtkTargetList
262  * @target: the interned atom representing the target
263  * @flags: the flags for this target
264  * @info: an ID that will be passed back to the application
265  * 
266  * Appends another target to a #GtkTargetList.
267  **/
268 void 
269 gtk_target_list_add (GtkTargetList *list,
270                      GdkAtom        target,
271                      guint          flags,
272                      guint          info)
273 {
274   GtkTargetPair *pair;
275
276   g_return_if_fail (list != NULL);
277   
278   pair = g_slice_new (GtkTargetPair);
279   pair->target = target;
280   pair->flags = flags;
281   pair->info = info;
282
283   list->list = g_list_append (list->list, pair);
284 }
285
286 static GdkAtom utf8_atom;
287 static GdkAtom text_atom;
288 static GdkAtom ctext_atom;
289 static GdkAtom text_plain_atom;
290 static GdkAtom text_plain_utf8_atom;
291 static GdkAtom text_plain_locale_atom;
292 static GdkAtom text_uri_list_atom;
293
294 static void 
295 init_atoms (void)
296 {
297   gchar *tmp;
298   const gchar *charset;
299
300   if (!utf8_atom)
301     {
302       utf8_atom = gdk_atom_intern_static_string ("UTF8_STRING");
303       text_atom = gdk_atom_intern_static_string ("TEXT");
304       ctext_atom = gdk_atom_intern_static_string ("COMPOUND_TEXT");
305       text_plain_atom = gdk_atom_intern_static_string ("text/plain");
306       text_plain_utf8_atom = gdk_atom_intern_static_string ("text/plain;charset=utf-8");
307       g_get_charset (&charset);
308       tmp = g_strdup_printf ("text/plain;charset=%s", charset);
309       text_plain_locale_atom = gdk_atom_intern (tmp, FALSE);
310       g_free (tmp);
311
312       text_uri_list_atom = gdk_atom_intern_static_string ("text/uri-list");
313     }
314 }
315
316 /**
317  * gtk_target_list_add_text_targets:
318  * @list: a #GtkTargetList
319  * @info: an ID that will be passed back to the application
320  * 
321  * Appends the text targets supported by #GtkSelection to
322  * the target list. All targets are added with the same @info.
323  * 
324  * Since: 2.6
325  **/
326 void 
327 gtk_target_list_add_text_targets (GtkTargetList *list,
328                                   guint          info)
329 {
330   g_return_if_fail (list != NULL);
331   
332   init_atoms ();
333
334   /* Keep in sync with gtk_selection_data_targets_include_text()
335    */
336   gtk_target_list_add (list, utf8_atom, 0, info);  
337   gtk_target_list_add (list, ctext_atom, 0, info);  
338   gtk_target_list_add (list, text_atom, 0, info);  
339   gtk_target_list_add (list, GDK_TARGET_STRING, 0, info);  
340   gtk_target_list_add (list, text_plain_utf8_atom, 0, info);  
341   if (!g_get_charset (NULL))
342     gtk_target_list_add (list, text_plain_locale_atom, 0, info);  
343   gtk_target_list_add (list, text_plain_atom, 0, info);  
344 }
345
346 /**
347  * gtk_target_list_add_rich_text_targets:
348  * @list: a #GtkTargetList
349  * @info: an ID that will be passed back to the application
350  * @deserializable: if %TRUE, then deserializable rich text formats
351  *                  will be added, serializable formats otherwise.
352  * @buffer: a #GtkTextBuffer.
353  *
354  * Appends the rich text targets registered with
355  * gtk_text_buffer_register_serialize_format() or
356  * gtk_text_buffer_register_deserialize_format() to the target list. All
357  * targets are added with the same @info.
358  *
359  * Since: 2.10
360  **/
361 void
362 gtk_target_list_add_rich_text_targets (GtkTargetList  *list,
363                                        guint           info,
364                                        gboolean        deserializable,
365                                        GtkTextBuffer  *buffer)
366 {
367   GdkAtom *atoms;
368   gint     n_atoms;
369   gint     i;
370
371   g_return_if_fail (list != NULL);
372   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
373
374   if (deserializable)
375     atoms = gtk_text_buffer_get_deserialize_formats (buffer, &n_atoms);
376   else
377     atoms = gtk_text_buffer_get_serialize_formats (buffer, &n_atoms);
378
379   for (i = 0; i < n_atoms; i++)
380     gtk_target_list_add (list, atoms[i], 0, info);
381
382   g_free (atoms);
383 }
384
385 /**
386  * gtk_target_list_add_image_targets:
387  * @list: a #GtkTargetList
388  * @info: an ID that will be passed back to the application
389  * @writable: whether to add only targets for which GTK+ knows
390  *   how to convert a pixbuf into the format
391  * 
392  * Appends the image targets supported by #GtkSelection to
393  * the target list. All targets are added with the same @info.
394  * 
395  * Since: 2.6
396  **/
397 void 
398 gtk_target_list_add_image_targets (GtkTargetList *list,
399                                    guint          info,
400                                    gboolean       writable)
401 {
402   GSList *formats, *f;
403   gchar **mimes, **m;
404   GdkAtom atom;
405
406   g_return_if_fail (list != NULL);
407
408   formats = gdk_pixbuf_get_formats ();
409
410   /* Make sure png comes first */
411   for (f = formats; f; f = f->next)
412     {
413       GdkPixbufFormat *fmt = f->data;
414       gchar *name; 
415  
416       name = gdk_pixbuf_format_get_name (fmt);
417       if (strcmp (name, "png") == 0)
418         {
419           formats = g_slist_delete_link (formats, f);
420           formats = g_slist_prepend (formats, fmt);
421
422           g_free (name);
423
424           break;
425         }
426
427       g_free (name);
428     }  
429
430   for (f = formats; f; f = f->next)
431     {
432       GdkPixbufFormat *fmt = f->data;
433
434       if (writable && !gdk_pixbuf_format_is_writable (fmt))
435         continue;
436       
437       mimes = gdk_pixbuf_format_get_mime_types (fmt);
438       for (m = mimes; *m; m++)
439         {
440           atom = gdk_atom_intern (*m, FALSE);
441           gtk_target_list_add (list, atom, 0, info);  
442         }
443       g_strfreev (mimes);
444     }
445
446   g_slist_free (formats);
447 }
448
449 /**
450  * gtk_target_list_add_uri_targets:
451  * @list: a #GtkTargetList
452  * @info: an ID that will be passed back to the application
453  * 
454  * Appends the URI targets supported by #GtkSelection to
455  * the target list. All targets are added with the same @info.
456  * 
457  * Since: 2.6
458  **/
459 void 
460 gtk_target_list_add_uri_targets (GtkTargetList *list,
461                                  guint          info)
462 {
463   g_return_if_fail (list != NULL);
464   
465   init_atoms ();
466
467   gtk_target_list_add (list, text_uri_list_atom, 0, info);  
468 }
469
470 /**
471  * gtk_target_list_add_table:
472  * @list: a #GtkTargetList
473  * @targets: the table of #GtkTargetEntry
474  * @ntargets: number of targets in the table
475  * 
476  * Prepends a table of #GtkTargetEntry to a target list.
477  **/
478 void               
479 gtk_target_list_add_table (GtkTargetList        *list,
480                            const GtkTargetEntry *targets,
481                            guint                 ntargets)
482 {
483   gint i;
484
485   for (i=ntargets-1; i >= 0; i--)
486     {
487       GtkTargetPair *pair = g_slice_new (GtkTargetPair);
488       pair->target = gdk_atom_intern (targets[i].target, FALSE);
489       pair->flags = targets[i].flags;
490       pair->info = targets[i].info;
491       
492       list->list = g_list_prepend (list->list, pair);
493     }
494 }
495
496 /**
497  * gtk_target_list_remove:
498  * @list: a #GtkTargetList
499  * @target: the interned atom representing the target
500  * 
501  * Removes a target from a target list.
502  **/
503 void 
504 gtk_target_list_remove (GtkTargetList *list,
505                         GdkAtom            target)
506 {
507   GList *tmp_list;
508
509   g_return_if_fail (list != NULL);
510
511   tmp_list = list->list;
512   while (tmp_list)
513     {
514       GtkTargetPair *pair = tmp_list->data;
515       
516       if (pair->target == target)
517         {
518           g_slice_free (GtkTargetPair, pair);
519
520           list->list = g_list_remove_link (list->list, tmp_list);
521           g_list_free_1 (tmp_list);
522
523           return;
524         }
525       
526       tmp_list = tmp_list->next;
527     }
528 }
529
530 /**
531  * gtk_target_list_find:
532  * @list: a #GtkTargetList
533  * @target: an interned atom representing the target to search for
534  * @info: a pointer to the location to store application info for target,
535  *        or %NULL
536  *
537  * Looks up a given target in a #GtkTargetList.
538  *
539  * Return value: %TRUE if the target was found, otherwise %FALSE
540  **/
541 gboolean
542 gtk_target_list_find (GtkTargetList *list,
543                       GdkAtom        target,
544                       guint         *info)
545 {
546   GList *tmp_list;
547
548   g_return_val_if_fail (list != NULL, FALSE);
549
550   tmp_list = list->list;
551   while (tmp_list)
552     {
553       GtkTargetPair *pair = tmp_list->data;
554
555       if (pair->target == target)
556         {
557           if (info)
558             *info = pair->info;
559
560           return TRUE;
561         }
562
563       tmp_list = tmp_list->next;
564     }
565
566   return FALSE;
567 }
568
569 /**
570  * gtk_target_table_new_from_list:
571  * @list: a #GtkTargetList
572  * @n_targets: return location for the number ot targets in the table
573  *
574  * This function creates an #GtkTargetEntry array that contains the
575  * same targets as the passed %list. The returned table is newly
576  * allocated and should be freed using gtk_target_table_free() when no
577  * longer needed.
578  *
579  * Return value: the new table.
580  *
581  * Since: 2.10
582  **/
583 GtkTargetEntry *
584 gtk_target_table_new_from_list (GtkTargetList *list,
585                                 gint          *n_targets)
586 {
587   GtkTargetEntry *targets;
588   GList          *tmp_list;
589   gint            i;
590
591   g_return_val_if_fail (list != NULL, NULL);
592   g_return_val_if_fail (n_targets != NULL, NULL);
593
594   *n_targets = g_list_length (list->list);
595   targets = g_new0 (GtkTargetEntry, *n_targets);
596
597   for (i = 0, tmp_list = list->list;
598        i < *n_targets;
599        i++, tmp_list = g_list_next (tmp_list))
600     {
601       GtkTargetPair *pair = tmp_list->data;
602
603       targets[i].target = gdk_atom_name (pair->target);
604       targets[i].flags  = pair->flags;
605       targets[i].info   = pair->info;
606     }
607
608   return targets;
609 }
610
611 /**
612  * gtk_target_table_free:
613  * @targets: a #GtkTargetEntry array
614  * @n_targets: the number of entries in the array
615  *
616  * This function frees a target table as returned by
617  * gtk_target_table_new_from_list()
618  *
619  * Since: 2.10
620  **/
621 void
622 gtk_target_table_free (GtkTargetEntry *targets,
623                        gint            n_targets)
624 {
625   gint i;
626
627   g_return_if_fail (targets == NULL || n_targets > 0);
628
629   for (i = 0; i < n_targets; i++)
630     g_free (targets[i].target);
631
632   g_free (targets);
633 }
634
635 /**
636  * gtk_selection_owner_set_for_display:
637  * @display: the #Gdkdisplay where the selection is set 
638  * @widget: new selection owner (a #GdkWidget), or %NULL.
639  * @selection: an interned atom representing the selection to claim.
640  * @time_: timestamp with which to claim the selection
641  *
642  * Claim ownership of a given selection for a particular widget, or,
643  * if @widget is %NULL, release ownership of the selection.
644  *
645  * Return value: TRUE if the operation succeeded 
646  * 
647  * Since: 2.2
648  */
649 gboolean
650 gtk_selection_owner_set_for_display (GdkDisplay   *display,
651                                      GtkWidget    *widget,
652                                      GdkAtom       selection,
653                                      guint32       time)
654 {
655   GList *tmp_list;
656   GtkWidget *old_owner;
657   GtkSelectionInfo *selection_info = NULL;
658   GdkWindow *window;
659
660   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
661   g_return_val_if_fail (selection != GDK_NONE, FALSE);
662   g_return_val_if_fail (widget == NULL || GTK_WIDGET_REALIZED (widget), FALSE);
663   g_return_val_if_fail (widget == NULL || gtk_widget_get_display (widget) == display, FALSE);
664   
665   if (widget == NULL)
666     window = NULL;
667   else
668     window = widget->window;
669
670   tmp_list = current_selections;
671   while (tmp_list)
672     {
673       if (((GtkSelectionInfo *)tmp_list->data)->selection == selection)
674         {
675           selection_info = tmp_list->data;
676           break;
677         }
678       
679       tmp_list = tmp_list->next;
680     }
681   
682   if (gdk_selection_owner_set_for_display (display, window, selection, time, TRUE))
683     {
684       old_owner = NULL;
685       
686       if (widget == NULL)
687         {
688           if (selection_info)
689             {
690               old_owner = selection_info->widget;
691               current_selections = g_list_remove_link (current_selections,
692                                                        tmp_list);
693               g_list_free (tmp_list);
694               g_slice_free (GtkSelectionInfo, selection_info);
695             }
696         }
697       else
698         {
699           if (selection_info == NULL)
700             {
701               selection_info = g_slice_new (GtkSelectionInfo);
702               selection_info->selection = selection;
703               selection_info->widget = widget;
704               selection_info->time = time;
705               selection_info->display = display;
706               current_selections = g_list_prepend (current_selections,
707                                                    selection_info);
708             }
709           else
710             {
711               old_owner = selection_info->widget;
712               selection_info->widget = widget;
713               selection_info->time = time;
714               selection_info->display = display;
715             }
716         }
717       /* If another widget in the application lost the selection,
718        *  send it a GDK_SELECTION_CLEAR event.
719        */
720       if (old_owner && old_owner != widget)
721         {
722           GdkEvent *event = gdk_event_new (GDK_SELECTION_CLEAR);
723           
724           event->selection.window = g_object_ref (old_owner->window);
725           event->selection.selection = selection;
726           event->selection.time = time;
727           
728           gtk_widget_event (old_owner, event);
729
730           gdk_event_free (event);
731         }
732       return TRUE;
733     }
734   else
735     return FALSE;
736 }
737
738 /**
739  * gtk_selection_owner_set:
740  * @widget:  a #GtkWidget, or %NULL.
741  * @selection:  an interned atom representing the selection to claim
742  * @time_: timestamp with which to claim the selection
743  * 
744  * Claims ownership of a given selection for a particular widget,
745  * or, if @widget is %NULL, release ownership of the selection.
746  * 
747  * Return value: %TRUE if the operation succeeded
748  **/
749 gboolean
750 gtk_selection_owner_set (GtkWidget *widget,
751                          GdkAtom    selection,
752                          guint32    time)
753 {
754   GdkDisplay *display;
755   
756   g_return_val_if_fail (widget == NULL || GTK_WIDGET_REALIZED (widget), FALSE);
757   g_return_val_if_fail (selection != GDK_NONE, FALSE);
758
759   if (widget)
760     display = gtk_widget_get_display (widget);
761   else
762     {
763       GTK_NOTE (MULTIHEAD,
764                 g_warning ("gtk_selection_owner_set (NULL,...) is not multihead safe"));
765                  
766       display = gdk_display_get_default ();
767     }
768   
769   return gtk_selection_owner_set_for_display (display, widget,
770                                               selection, time);
771 }
772
773 typedef struct _GtkSelectionTargetList GtkSelectionTargetList;
774
775 struct _GtkSelectionTargetList {
776   GdkAtom selection;
777   GtkTargetList *list;
778 };
779
780 static GtkTargetList *
781 gtk_selection_target_list_get (GtkWidget    *widget,
782                                GdkAtom       selection)
783 {
784   GtkSelectionTargetList *sellist;
785   GList *tmp_list;
786   GList *lists;
787
788   lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
789   
790   tmp_list = lists;
791   while (tmp_list)
792     {
793       sellist = tmp_list->data;
794       if (sellist->selection == selection)
795         return sellist->list;
796       tmp_list = tmp_list->next;
797     }
798
799   sellist = g_slice_new (GtkSelectionTargetList);
800   sellist->selection = selection;
801   sellist->list = gtk_target_list_new (NULL, 0);
802
803   lists = g_list_prepend (lists, sellist);
804   g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
805
806   return sellist->list;
807 }
808
809 static void
810 gtk_selection_target_list_remove (GtkWidget    *widget)
811 {
812   GtkSelectionTargetList *sellist;
813   GList *tmp_list;
814   GList *lists;
815
816   lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
817   
818   tmp_list = lists;
819   while (tmp_list)
820     {
821       sellist = tmp_list->data;
822
823       gtk_target_list_unref (sellist->list);
824
825       g_slice_free (GtkSelectionTargetList, sellist);
826       tmp_list = tmp_list->next;
827     }
828
829   g_list_free (lists);
830   g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), NULL);
831 }
832
833 /**
834  * gtk_selection_clear_targets:
835  * @widget:    a #GtkWidget
836  * @selection: an atom representing a selection
837  *
838  * Remove all targets registered for the given selection for the
839  * widget.
840  **/
841 void 
842 gtk_selection_clear_targets (GtkWidget *widget,
843                              GdkAtom    selection)
844 {
845   GtkSelectionTargetList *sellist;
846   GList *tmp_list;
847   GList *lists;
848
849   g_return_if_fail (GTK_IS_WIDGET (widget));
850   g_return_if_fail (selection != GDK_NONE);
851
852   lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
853   
854   tmp_list = lists;
855   while (tmp_list)
856     {
857       sellist = tmp_list->data;
858       if (sellist->selection == selection)
859         {
860           lists = g_list_delete_link (lists, tmp_list);
861           gtk_target_list_unref (sellist->list);
862           g_slice_free (GtkSelectionTargetList, sellist);
863
864           break;
865         }
866       
867       tmp_list = tmp_list->next;
868     }
869   
870   g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
871 }
872
873 /**
874  * gtk_selection_add_target:
875  * @widget:  a #GtkTarget
876  * @selection: the selection
877  * @target: target to add.
878  * @info: A unsigned integer which will be passed back to the application.
879  * 
880  * Appends a specified target to the list of supported targets for a 
881  * given widget and selection.
882  **/
883 void 
884 gtk_selection_add_target (GtkWidget         *widget, 
885                           GdkAtom            selection,
886                           GdkAtom            target,
887                           guint              info)
888 {
889   GtkTargetList *list;
890
891   g_return_if_fail (GTK_IS_WIDGET (widget));
892   g_return_if_fail (selection != GDK_NONE);
893
894   list = gtk_selection_target_list_get (widget, selection);
895   gtk_target_list_add (list, target, 0, info);
896 #ifdef GDK_WINDOWING_WIN32
897   gdk_win32_selection_add_targets (widget->window, selection, 1, &target);
898 #endif
899 }
900
901 /**
902  * gtk_selection_add_targets:
903  * @widget: a #GtkWidget
904  * @selection: the selection
905  * @targets: a table of targets to add
906  * @ntargets:  number of entries in @targets
907  * 
908  * Prepends a table of targets to the list of supported targets
909  * for a given widget and selection.
910  **/
911 void 
912 gtk_selection_add_targets (GtkWidget            *widget, 
913                            GdkAtom               selection,
914                            const GtkTargetEntry *targets,
915                            guint                 ntargets)
916 {
917   GtkTargetList *list;
918
919   g_return_if_fail (GTK_IS_WIDGET (widget));
920   g_return_if_fail (selection != GDK_NONE);
921   g_return_if_fail (targets != NULL);
922   
923   list = gtk_selection_target_list_get (widget, selection);
924   gtk_target_list_add_table (list, targets, ntargets);
925
926 #ifdef GDK_WINDOWING_WIN32
927   {
928     int i;
929     GdkAtom *atoms = g_new (GdkAtom, ntargets);
930
931     for (i = 0; i < ntargets; ++i)
932       atoms[i] = gdk_atom_intern (targets[i].target, FALSE);
933     gdk_win32_selection_add_targets (widget->window, selection, ntargets, atoms);
934     g_free (atoms);
935   }
936 #endif
937 }
938
939
940 /**
941  * gtk_selection_remove_all:
942  * @widget: a #GtkWidget 
943  * 
944  * Removes all handlers and unsets ownership of all 
945  * selections for a widget. Called when widget is being
946  * destroyed. This function will not generally be
947  * called by applications.
948  **/
949 void
950 gtk_selection_remove_all (GtkWidget *widget)
951 {
952   GList *tmp_list;
953   GList *next;
954   GtkSelectionInfo *selection_info;
955
956   g_return_if_fail (GTK_IS_WIDGET (widget));
957
958   /* Remove pending requests/incrs for this widget */
959   
960   tmp_list = current_retrievals;
961   while (tmp_list)
962     {
963       next = tmp_list->next;
964       if (((GtkRetrievalInfo *)tmp_list->data)->widget == widget)
965         {
966           current_retrievals = g_list_remove_link (current_retrievals, 
967                                                    tmp_list);
968           /* structure will be freed in timeout */
969           g_list_free (tmp_list);
970         }
971       tmp_list = next;
972     }
973   
974   /* Disclaim ownership of any selections */
975   
976   tmp_list = current_selections;
977   while (tmp_list)
978     {
979       next = tmp_list->next;
980       selection_info = (GtkSelectionInfo *)tmp_list->data;
981       
982       if (selection_info->widget == widget)
983         {       
984           gdk_selection_owner_set_for_display (selection_info->display,
985                                                NULL, 
986                                                selection_info->selection,
987                                                GDK_CURRENT_TIME, FALSE);
988           current_selections = g_list_remove_link (current_selections,
989                                                    tmp_list);
990           g_list_free (tmp_list);
991           g_slice_free (GtkSelectionInfo, selection_info);
992         }
993       
994       tmp_list = next;
995     }
996
997   /* Remove all selection lists */
998   gtk_selection_target_list_remove (widget);
999 }
1000
1001
1002 /**
1003  * gtk_selection_convert:
1004  * @widget: The widget which acts as requestor
1005  * @selection: Which selection to get
1006  * @target: Form of information desired (e.g., STRING)
1007  * @time_: Time of request (usually of triggering event)
1008        In emergency, you could use #GDK_CURRENT_TIME
1009  * 
1010  * Requests the contents of a selection. When received, 
1011  * a "selection-received" signal will be generated.
1012  * 
1013  * Return value: %TRUE if requested succeeded. %FALSE if we could not process
1014  *          request. (e.g., there was already a request in process for
1015  *          this widget).
1016  **/
1017 gboolean
1018 gtk_selection_convert (GtkWidget *widget, 
1019                        GdkAtom    selection, 
1020                        GdkAtom    target,
1021                        guint32    time_)
1022 {
1023   GtkRetrievalInfo *info;
1024   GList *tmp_list;
1025   GdkWindow *owner_window;
1026   GdkDisplay *display;
1027   
1028   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
1029   g_return_val_if_fail (selection != GDK_NONE, FALSE);
1030   
1031   if (initialize)
1032     gtk_selection_init ();
1033   
1034   if (!GTK_WIDGET_REALIZED (widget))
1035     gtk_widget_realize (widget);
1036   
1037   /* Check to see if there are already any retrievals in progress for
1038      this widget. If we changed GDK to use the selection for the 
1039      window property in which to store the retrieved information, then
1040      we could support multiple retrievals for different selections.
1041      This might be useful for DND. */
1042   
1043   tmp_list = current_retrievals;
1044   while (tmp_list)
1045     {
1046       info = (GtkRetrievalInfo *)tmp_list->data;
1047       if (info->widget == widget)
1048         return FALSE;
1049       tmp_list = tmp_list->next;
1050     }
1051   
1052   info = g_slice_new (GtkRetrievalInfo);
1053   
1054   info->widget = widget;
1055   info->selection = selection;
1056   info->target = target;
1057   info->idle_time = 0;
1058   info->buffer = NULL;
1059   info->offset = -1;
1060   
1061   /* Check if this process has current owner. If so, call handler
1062      procedure directly to avoid deadlocks with INCR. */
1063
1064   display = gtk_widget_get_display (widget);
1065   owner_window = gdk_selection_owner_get_for_display (display, selection);
1066   
1067   if (owner_window != NULL)
1068     {
1069       GtkWidget *owner_widget;
1070       gpointer owner_widget_ptr;
1071       GtkSelectionData selection_data;
1072       
1073       selection_data.selection = selection;
1074       selection_data.target = target;
1075       selection_data.data = NULL;
1076       selection_data.length = -1;
1077       selection_data.display = display;
1078       
1079       gdk_window_get_user_data (owner_window, &owner_widget_ptr);
1080       owner_widget = owner_widget_ptr;
1081       
1082       if (owner_widget != NULL)
1083         {
1084           gtk_selection_invoke_handler (owner_widget, 
1085                                         &selection_data,
1086                                         time_);
1087           
1088           gtk_selection_retrieval_report (info,
1089                                           selection_data.type, 
1090                                           selection_data.format,
1091                                           selection_data.data,
1092                                           selection_data.length,
1093                                           time_);
1094           
1095           g_free (selection_data.data);
1096           selection_data.data = NULL;
1097           selection_data.length = -1;
1098           
1099           g_slice_free (GtkRetrievalInfo, info);
1100           return TRUE;
1101         }
1102     }
1103   
1104   /* Otherwise, we need to go through X */
1105   
1106   current_retrievals = g_list_append (current_retrievals, info);
1107   gdk_selection_convert (widget->window, selection, target, time_);
1108   gdk_threads_add_timeout (1000,
1109       (GSourceFunc) gtk_selection_retrieval_timeout, info);
1110   
1111   return TRUE;
1112 }
1113
1114 /**
1115  * gtk_selection_data_get_selection:
1116  * @selection_data: a pointer to a #GtkSelectionData structure.
1117  *
1118  * Retrieves the selection #GdkAtom of the selection data.
1119  *
1120  * Returns: the selection #GdkAtom of the selection data.
1121  *
1122  * Since: 2.16
1123  **/
1124 GdkAtom
1125 gtk_selection_data_get_selection (GtkSelectionData *selection_data)
1126 {
1127   g_return_val_if_fail (selection_data != NULL, 0);
1128
1129   return selection_data->selection;
1130 }
1131
1132 /**
1133  * gtk_selection_data_get_target:
1134  * @selection_data: a pointer to a #GtkSelectionData structure.
1135  *
1136  * Retrieves the target of the selection.
1137  *
1138  * Returns:  the target of the selection.
1139  *
1140  * Since: 2.14
1141  **/
1142 GdkAtom
1143 gtk_selection_data_get_target (GtkSelectionData *selection_data)
1144 {
1145   g_return_val_if_fail (selection_data != NULL, 0);
1146
1147   return selection_data->target;
1148 }
1149
1150 /**
1151  * gtk_selection_data_get_data_type:
1152  * @selection_data: a pointer to a #GtkSelectionData structure.
1153  *
1154  * Retrieves the data type of the selection.
1155  *
1156  * Returns:  the data type of the selection.
1157  *
1158  * Since: 2.14
1159  **/
1160 GdkAtom
1161 gtk_selection_data_get_data_type (GtkSelectionData *selection_data)
1162 {
1163   g_return_val_if_fail (selection_data != NULL, 0);
1164
1165   return selection_data->type;
1166 }
1167
1168 /**
1169  * gtk_selection_data_get_format:
1170  * @selection_data: a pointer to a #GtkSelectionData structure.
1171  *
1172  * Retrieves the format of the selection.
1173  *
1174  * Returns: the format of the selection.
1175  *
1176  * Since: 2.14
1177  **/
1178 gint
1179 gtk_selection_data_get_format (GtkSelectionData *selection_data)
1180 {
1181   g_return_val_if_fail (selection_data != NULL, 0);
1182
1183   return selection_data->format;
1184 }
1185
1186 /**
1187  * gtk_selection_data_get_data:
1188  * @selection_data: a pointer to a #GtkSelectionData structure.
1189  *
1190  * Retrieves the raw data of the selection.
1191  *
1192  * Returns: the raw data of the selection.
1193  *
1194  * Since: 2.14
1195  **/
1196 const guchar*
1197 gtk_selection_data_get_data (GtkSelectionData *selection_data)
1198 {
1199   g_return_val_if_fail (selection_data != NULL, NULL);
1200
1201   return selection_data->data;
1202 }
1203
1204 /**
1205  * gtk_selection_data_get_length:
1206  * @selection_data: a pointer to a #GtkSelectionData structure.
1207  *
1208  * Retrieves the length of the raw data of the selection.
1209  *
1210  * Returns: the length of the data of the selection.
1211  *
1212  * Since: 2.14
1213  */
1214 gint
1215 gtk_selection_data_get_length (GtkSelectionData *selection_data)
1216 {
1217   g_return_val_if_fail (selection_data != NULL, -1);
1218
1219   return selection_data->length;
1220 }
1221
1222 /**
1223  * gtk_selection_data_get_display:
1224  * @selection_data: a pointer to a #GtkSelectionData structure.
1225  *
1226  * Retrieves the display of the selection.
1227  *
1228  * Returns: the display of the selection.
1229  *
1230  * Since: 2.14
1231  **/
1232 GdkDisplay *
1233 gtk_selection_data_get_display (GtkSelectionData *selection_data)
1234 {
1235   g_return_val_if_fail (selection_data != NULL, NULL);
1236
1237   return selection_data->display;
1238 }
1239
1240 /**
1241  * gtk_selection_data_set:
1242  * @selection_data: a pointer to a #GtkSelectionData structure.
1243  * @type: the type of selection data
1244  * @format: format (number of bits in a unit)
1245  * @data: pointer to the data (will be copied)
1246  * @length: length of the data
1247  * 
1248  * Stores new data into a #GtkSelectionData object. Should
1249  * <emphasis>only</emphasis> be called from a selection handler callback.
1250  * Zero-terminates the stored data.
1251  **/
1252 void 
1253 gtk_selection_data_set (GtkSelectionData *selection_data,
1254                         GdkAtom           type,
1255                         gint              format,
1256                         const guchar     *data,
1257                         gint              length)
1258 {
1259   g_return_if_fail (selection_data != NULL);
1260
1261   g_free (selection_data->data);
1262   
1263   selection_data->type = type;
1264   selection_data->format = format;
1265   
1266   if (data)
1267     {
1268       selection_data->data = g_new (guchar, length+1);
1269       memcpy (selection_data->data, data, length);
1270       selection_data->data[length] = 0;
1271     }
1272   else
1273     {
1274       g_return_if_fail (length <= 0);
1275       
1276       if (length < 0)
1277         selection_data->data = NULL;
1278       else
1279         selection_data->data = (guchar *) g_strdup ("");
1280     }
1281   
1282   selection_data->length = length;
1283 }
1284
1285 static gboolean
1286 selection_set_string (GtkSelectionData *selection_data,
1287                       const gchar      *str,
1288                       gint              len)
1289 {
1290   gchar *tmp = g_strndup (str, len);
1291   gchar *latin1 = gdk_utf8_to_string_target (tmp);
1292   g_free (tmp);
1293   
1294   if (latin1)
1295     {
1296       gtk_selection_data_set (selection_data,
1297                               GDK_SELECTION_TYPE_STRING,
1298                               8, (guchar *) latin1, strlen (latin1));
1299       g_free (latin1);
1300       
1301       return TRUE;
1302     }
1303   else
1304     return FALSE;
1305 }
1306
1307 static gboolean
1308 selection_set_compound_text (GtkSelectionData *selection_data,
1309                              const gchar      *str,
1310                              gint              len)
1311 {
1312   gchar *tmp;
1313   guchar *text;
1314   GdkAtom encoding;
1315   gint format;
1316   gint new_length;
1317   gboolean result = FALSE;
1318   
1319   tmp = g_strndup (str, len);
1320   if (gdk_utf8_to_compound_text_for_display (selection_data->display, tmp,
1321                                              &encoding, &format, &text, &new_length))
1322     {
1323       gtk_selection_data_set (selection_data, encoding, format, text, new_length);
1324       gdk_free_compound_text (text);
1325       
1326       result = TRUE;
1327     }
1328
1329   g_free (tmp);
1330
1331   return result;
1332 }
1333
1334 /* Normalize \r and \n into \r\n
1335  */
1336 static gchar *
1337 normalize_to_crlf (const gchar *str, 
1338                    gint         len)
1339 {
1340   GString *result = g_string_sized_new (len);
1341   const gchar *p = str;
1342   const gchar *end = str + len;
1343
1344   while (p < end)
1345     {
1346       if (*p == '\n')
1347         g_string_append_c (result, '\r');
1348
1349       if (*p == '\r')
1350         {
1351           g_string_append_c (result, *p);
1352           p++;
1353           if (p == end || *p != '\n')
1354             g_string_append_c (result, '\n');
1355           if (p == end)
1356             break;
1357         }
1358
1359       g_string_append_c (result, *p);
1360       p++;
1361     }
1362
1363   return g_string_free (result, FALSE);  
1364 }
1365
1366 /* Normalize \r and \r\n into \n
1367  */
1368 static gchar *
1369 normalize_to_lf (gchar *str, 
1370                  gint   len)
1371 {
1372   GString *result = g_string_sized_new (len);
1373   const gchar *p = str;
1374
1375   while (1)
1376     {
1377       if (*p == '\r')
1378         {
1379           p++;
1380           if (*p != '\n')
1381             g_string_append_c (result, '\n');
1382         }
1383
1384       if (*p == '\0')
1385         break;
1386
1387       g_string_append_c (result, *p);
1388       p++;
1389     }
1390
1391   return g_string_free (result, FALSE);  
1392 }
1393
1394 static gboolean
1395 selection_set_text_plain (GtkSelectionData *selection_data,
1396                           const gchar      *str,
1397                           gint              len)
1398 {
1399   const gchar *charset = NULL;
1400   gchar *result;
1401   GError *error = NULL;
1402
1403   result = normalize_to_crlf (str, len);
1404   if (selection_data->target == text_plain_atom)
1405     charset = "ASCII";
1406   else if (selection_data->target == text_plain_locale_atom)
1407     g_get_charset (&charset);
1408
1409   if (charset)
1410     {
1411       gchar *tmp = result;
1412       result = g_convert_with_fallback (tmp, -1, 
1413                                         charset, "UTF-8", 
1414                                         NULL, NULL, NULL, &error);
1415       g_free (tmp);
1416     }
1417
1418   if (!result)
1419     {
1420       g_warning ("Error converting from %s to %s: %s",
1421                  "UTF-8", charset, error->message);
1422       g_error_free (error);
1423       
1424       return FALSE;
1425     }
1426   
1427   gtk_selection_data_set (selection_data,
1428                           selection_data->target, 
1429                           8, (guchar *) result, strlen (result));
1430   g_free (result);
1431   
1432   return TRUE;
1433 }
1434
1435 static guchar *
1436 selection_get_text_plain (GtkSelectionData *selection_data)
1437 {
1438   const gchar *charset = NULL;
1439   gchar *str, *result;
1440   gsize len;
1441   GError *error = NULL;
1442
1443   str = g_strdup ((const gchar *) selection_data->data);
1444   len = selection_data->length;
1445   
1446   if (selection_data->type == text_plain_atom)
1447     charset = "ISO-8859-1";
1448   else if (selection_data->type == text_plain_locale_atom)
1449     g_get_charset (&charset);
1450
1451   if (charset)
1452     {
1453       gchar *tmp = str;
1454       str = g_convert_with_fallback (tmp, len, 
1455                                      "UTF-8", charset,
1456                                      NULL, NULL, &len, &error);
1457       g_free (tmp);
1458
1459       if (!str)
1460         {
1461           g_warning ("Error converting from %s to %s: %s",
1462                      charset, "UTF-8", error->message);
1463           g_error_free (error);
1464
1465           return NULL;
1466         }
1467     }
1468   else if (!g_utf8_validate (str, -1, NULL))
1469     {
1470       g_warning ("Error converting from %s to %s: %s",
1471                  "text/plain;charset=utf-8", "UTF-8", "invalid UTF-8");
1472       g_free (str);
1473
1474       return NULL;
1475     }
1476
1477   result = normalize_to_lf (str, len);
1478   g_free (str);
1479
1480   return (guchar *) result;
1481 }
1482
1483 /**
1484  * gtk_selection_data_set_text:
1485  * @selection_data: a #GtkSelectionData
1486  * @str: a UTF-8 string
1487  * @len: the length of @str, or -1 if @str is nul-terminated.
1488  * 
1489  * Sets the contents of the selection from a UTF-8 encoded string.
1490  * The string is converted to the form determined by
1491  * @selection_data->target.
1492  * 
1493  * Return value: %TRUE if the selection was successfully set,
1494  *   otherwise %FALSE.
1495  **/
1496 gboolean
1497 gtk_selection_data_set_text (GtkSelectionData     *selection_data,
1498                              const gchar          *str,
1499                              gint                  len)
1500 {
1501   g_return_val_if_fail (selection_data != NULL, FALSE);
1502
1503   if (len < 0)
1504     len = strlen (str);
1505   
1506   init_atoms ();
1507
1508   if (selection_data->target == utf8_atom)
1509     {
1510       gtk_selection_data_set (selection_data,
1511                               utf8_atom,
1512                               8, (guchar *)str, len);
1513       return TRUE;
1514     }
1515   else if (selection_data->target == GDK_TARGET_STRING)
1516     {
1517       return selection_set_string (selection_data, str, len);
1518     }
1519   else if (selection_data->target == ctext_atom ||
1520            selection_data->target == text_atom)
1521     {
1522       if (selection_set_compound_text (selection_data, str, len))
1523         return TRUE;
1524       else if (selection_data->target == text_atom)
1525         return selection_set_string (selection_data, str, len);
1526     }
1527   else if (selection_data->target == text_plain_atom ||
1528            selection_data->target == text_plain_utf8_atom ||
1529            selection_data->target == text_plain_locale_atom)
1530     {
1531       return selection_set_text_plain (selection_data, str, len);
1532     }
1533
1534   return FALSE;
1535 }
1536
1537 /**
1538  * gtk_selection_data_get_text:
1539  * @selection_data: a #GtkSelectionData
1540  * 
1541  * Gets the contents of the selection data as a UTF-8 string.
1542  * 
1543  * Return value: if the selection data contained a recognized
1544  *   text type and it could be converted to UTF-8, a newly allocated
1545  *   string containing the converted text, otherwise %NULL.
1546  *   If the result is non-%NULL it must be freed with g_free().
1547  **/
1548 guchar *
1549 gtk_selection_data_get_text (GtkSelectionData *selection_data)
1550 {
1551   guchar *result = NULL;
1552
1553   g_return_val_if_fail (selection_data != NULL, NULL);
1554
1555   init_atoms ();
1556   
1557   if (selection_data->length >= 0 &&
1558       (selection_data->type == GDK_TARGET_STRING ||
1559        selection_data->type == ctext_atom ||
1560        selection_data->type == utf8_atom))
1561     {
1562       gchar **list;
1563       gint i;
1564       gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1565                                                                selection_data->type,
1566                                                                selection_data->format, 
1567                                                                selection_data->data,
1568                                                                selection_data->length,
1569                                                                &list);
1570       if (count > 0)
1571         result = (guchar *) list[0];
1572
1573       for (i = 1; i < count; i++)
1574         g_free (list[i]);
1575       g_free (list);
1576     }
1577   else if (selection_data->length >= 0 &&
1578            (selection_data->type == text_plain_atom ||
1579             selection_data->type == text_plain_utf8_atom ||
1580             selection_data->type == text_plain_locale_atom))
1581     {
1582       result = selection_get_text_plain (selection_data);
1583     }
1584
1585   return result;
1586 }
1587
1588 /**
1589  * gtk_selection_data_set_pixbuf:
1590  * @selection_data: a #GtkSelectionData
1591  * @pixbuf: a #GdkPixbuf
1592  * 
1593  * Sets the contents of the selection from a #GdkPixbuf
1594  * The pixbuf is converted to the form determined by
1595  * @selection_data->target.
1596  * 
1597  * Return value: %TRUE if the selection was successfully set,
1598  *   otherwise %FALSE.
1599  *
1600  * Since: 2.6
1601  **/
1602 gboolean
1603 gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data,
1604                                GdkPixbuf        *pixbuf)
1605 {
1606   GSList *formats, *f;
1607   gchar **mimes, **m;
1608   GdkAtom atom;
1609   gboolean result;
1610   gchar *str, *type;
1611   gsize len;
1612
1613   g_return_val_if_fail (selection_data != NULL, FALSE);
1614   g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
1615
1616   formats = gdk_pixbuf_get_formats ();
1617
1618   for (f = formats; f; f = f->next)
1619     {
1620       GdkPixbufFormat *fmt = f->data;
1621
1622       mimes = gdk_pixbuf_format_get_mime_types (fmt);
1623       for (m = mimes; *m; m++)
1624         {
1625           atom = gdk_atom_intern (*m, FALSE);
1626           if (selection_data->target == atom)
1627             {
1628               str = NULL;
1629               type = gdk_pixbuf_format_get_name (fmt);
1630               result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
1631                                                   type, NULL,
1632                                                   ((strcmp (type, "png") == 0) ?
1633                                                    "compression" : NULL), "2",
1634                                                   NULL);
1635               if (result)
1636                 gtk_selection_data_set (selection_data,
1637                                         atom, 8, (guchar *)str, len);
1638               g_free (type);
1639               g_free (str);
1640               g_strfreev (mimes);
1641               g_slist_free (formats);
1642
1643               return result;
1644             }
1645         }
1646
1647       g_strfreev (mimes);
1648     }
1649
1650   g_slist_free (formats);
1651  
1652   return FALSE;
1653 }
1654
1655 /**
1656  * gtk_selection_data_get_pixbuf:
1657  * @selection_data: a #GtkSelectionData
1658  * 
1659  * Gets the contents of the selection data as a #GdkPixbuf.
1660  * 
1661  * Return value: if the selection data contained a recognized
1662  *   image type and it could be converted to a #GdkPixbuf, a 
1663  *   newly allocated pixbuf is returned, otherwise %NULL.
1664  *   If the result is non-%NULL it must be freed with g_object_unref().
1665  *
1666  * Since: 2.6
1667  **/
1668 GdkPixbuf *
1669 gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data)
1670 {
1671   GdkPixbufLoader *loader;
1672   GdkPixbuf *result = NULL;
1673
1674   g_return_val_if_fail (selection_data != NULL, NULL);
1675
1676   if (selection_data->length > 0)
1677     {
1678       loader = gdk_pixbuf_loader_new ();
1679       
1680       gdk_pixbuf_loader_write (loader, 
1681                                selection_data->data,
1682                                selection_data->length,
1683                                NULL);
1684       gdk_pixbuf_loader_close (loader, NULL);
1685       result = gdk_pixbuf_loader_get_pixbuf (loader);
1686       
1687       if (result)
1688         g_object_ref (result);
1689       
1690       g_object_unref (loader);
1691     }
1692
1693   return result;
1694 }
1695
1696 /**
1697  * gtk_selection_data_set_uris:
1698  * @selection_data: a #GtkSelectionData
1699  * @uris: a %NULL-terminated array of strings hilding URIs
1700  * 
1701  * Sets the contents of the selection from a list of URIs.
1702  * The string is converted to the form determined by
1703  * @selection_data->target.
1704  * 
1705  * Return value: %TRUE if the selection was successfully set,
1706  *   otherwise %FALSE.
1707  *
1708  * Since: 2.6
1709  **/
1710 gboolean
1711 gtk_selection_data_set_uris (GtkSelectionData  *selection_data,
1712                              gchar            **uris)
1713 {
1714   g_return_val_if_fail (selection_data != NULL, FALSE);
1715   g_return_val_if_fail (uris != NULL, FALSE);
1716
1717   init_atoms ();
1718
1719   if (selection_data->target == text_uri_list_atom)
1720     {
1721       GString *list;
1722       gint i;
1723       gchar *result;
1724       gsize length;
1725       
1726       list = g_string_new (NULL);
1727       for (i = 0; uris[i]; i++)
1728         {
1729           g_string_append (list, uris[i]);
1730           g_string_append (list, "\r\n");
1731         }
1732
1733       result = g_convert (list->str, list->len,
1734                           "ASCII", "UTF-8", 
1735                           NULL, &length, NULL);
1736       g_string_free (list, TRUE);
1737       
1738       if (result)
1739         {
1740           gtk_selection_data_set (selection_data,
1741                                   text_uri_list_atom,
1742                                   8, (guchar *)result, length);
1743           
1744           g_free (result);
1745
1746           return TRUE;
1747         }
1748     }
1749
1750   return FALSE;
1751 }
1752
1753 /**
1754  * gtk_selection_data_get_uris:
1755  * @selection_data: a #GtkSelectionData
1756  * 
1757  * Gets the contents of the selection data as array of URIs.
1758  * 
1759  * Return value: if the selection data contains a list of
1760  *   URIs, a newly allocated %NULL-terminated string array
1761  *   containing the URIs, otherwise %NULL. If the result is 
1762  *   non-%NULL it must be freed with g_strfreev().
1763  *
1764  * Since: 2.6
1765  **/
1766 gchar **
1767 gtk_selection_data_get_uris (GtkSelectionData *selection_data)
1768 {
1769   gchar **result = NULL;
1770
1771   g_return_val_if_fail (selection_data != NULL, NULL);
1772
1773   init_atoms ();
1774   
1775   if (selection_data->length >= 0 &&
1776       selection_data->type == text_uri_list_atom)
1777     {
1778       gchar **list;
1779       gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1780                                                                utf8_atom,
1781                                                                selection_data->format, 
1782                                                                selection_data->data,
1783                                                                selection_data->length,
1784                                                                &list);
1785       if (count > 0)
1786         result = g_uri_list_extract_uris (list[0]);
1787       
1788       g_strfreev (list);
1789     }
1790
1791   return result;
1792 }
1793
1794
1795 /**
1796  * gtk_selection_data_get_targets:
1797  * @selection_data: a #GtkSelectionData object
1798  * @targets: location to store an array of targets. The result
1799  *           stored here must be freed with g_free().
1800  * @n_atoms: location to store number of items in @targets.
1801  * 
1802  * Gets the contents of @selection_data as an array of targets.
1803  * This can be used to interpret the results of getting
1804  * the standard TARGETS target that is always supplied for
1805  * any selection.
1806  * 
1807  * Return value: %TRUE if @selection_data contains a valid
1808  *    array of targets, otherwise %FALSE.
1809  **/
1810 gboolean
1811 gtk_selection_data_get_targets (GtkSelectionData  *selection_data,
1812                                 GdkAtom          **targets,
1813                                 gint              *n_atoms)
1814 {
1815   g_return_val_if_fail (selection_data != NULL, FALSE);
1816
1817   if (selection_data->length >= 0 &&
1818       selection_data->format == 32 &&
1819       selection_data->type == GDK_SELECTION_TYPE_ATOM)
1820     {
1821       if (targets)
1822         *targets = g_memdup (selection_data->data, selection_data->length);
1823       if (n_atoms)
1824         *n_atoms = selection_data->length / sizeof (GdkAtom);
1825
1826       return TRUE;
1827     }
1828   else
1829     {
1830       if (targets)
1831         *targets = NULL;
1832       if (n_atoms)
1833         *n_atoms = -1;
1834
1835       return FALSE;
1836     }
1837 }
1838
1839 /**
1840  * gtk_targets_include_text:
1841  * @targets: an array of #GdkAtom<!-- -->s
1842  * @n_targets: the length of @targets
1843  * 
1844  * Determines if any of the targets in @targets can be used to
1845  * provide text.
1846  * 
1847  * Return value: %TRUE if @targets include a suitable target for text,
1848  *   otherwise %FALSE.
1849  *
1850  * Since: 2.10
1851  **/
1852 gboolean 
1853 gtk_targets_include_text (GdkAtom *targets,
1854                           gint     n_targets)
1855 {
1856   gint i;
1857   gboolean result = FALSE;
1858
1859   g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1860
1861   /* Keep in sync with gtk_target_list_add_text_targets()
1862    */
1863  
1864   init_atoms ();
1865  
1866   for (i = 0; i < n_targets; i++)
1867     {
1868       if (targets[i] == utf8_atom ||
1869           targets[i] == text_atom ||
1870           targets[i] == GDK_TARGET_STRING ||
1871           targets[i] == ctext_atom ||
1872           targets[i] == text_plain_atom ||
1873           targets[i] == text_plain_utf8_atom ||
1874           targets[i] == text_plain_locale_atom)
1875         {
1876           result = TRUE;
1877           break;
1878         }
1879     }
1880   
1881   return result;
1882 }
1883
1884 /**
1885  * gtk_targets_include_rich_text:
1886  * @targets: an array of #GdkAtom<!-- -->s
1887  * @n_targets: the length of @targets
1888  * @buffer: a #GtkTextBuffer
1889  *
1890  * Determines if any of the targets in @targets can be used to
1891  * provide rich text.
1892  *
1893  * Return value: %TRUE if @targets include a suitable target for rich text,
1894  *               otherwise %FALSE.
1895  *
1896  * Since: 2.10
1897  **/
1898 gboolean
1899 gtk_targets_include_rich_text (GdkAtom       *targets,
1900                                gint           n_targets,
1901                                GtkTextBuffer *buffer)
1902 {
1903   GdkAtom *rich_targets;
1904   gint n_rich_targets;
1905   gint i, j;
1906   gboolean result = FALSE;
1907
1908   g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
1909   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1910
1911   init_atoms ();
1912
1913   rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
1914                                                           &n_rich_targets);
1915
1916   for (i = 0; i < n_targets; i++)
1917     {
1918       for (j = 0; j < n_rich_targets; j++)
1919         {
1920           if (targets[i] == rich_targets[j])
1921             {
1922               result = TRUE;
1923               goto done;
1924             }
1925         }
1926     }
1927
1928  done:
1929   g_free (rich_targets);
1930
1931   return result;
1932 }
1933
1934 /**
1935  * gtk_selection_data_targets_include_text:
1936  * @selection_data: a #GtkSelectionData object
1937  * 
1938  * Given a #GtkSelectionData object holding a list of targets,
1939  * determines if any of the targets in @targets can be used to
1940  * provide text.
1941  * 
1942  * Return value: %TRUE if @selection_data holds a list of targets,
1943  *   and a suitable target for text is included, otherwise %FALSE.
1944  **/
1945 gboolean
1946 gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
1947 {
1948   GdkAtom *targets;
1949   gint n_targets;
1950   gboolean result = FALSE;
1951
1952   g_return_val_if_fail (selection_data != NULL, FALSE);
1953
1954   init_atoms ();
1955
1956   if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1957     {
1958       result = gtk_targets_include_text (targets, n_targets);
1959       g_free (targets);
1960     }
1961
1962   return result;
1963 }
1964
1965 /**
1966  * gtk_selection_data_targets_include_rich_text:
1967  * @selection_data: a #GtkSelectionData object
1968  * @buffer: a #GtkTextBuffer
1969  *
1970  * Given a #GtkSelectionData object holding a list of targets,
1971  * determines if any of the targets in @targets can be used to
1972  * provide rich text.
1973  *
1974  * Return value: %TRUE if @selection_data holds a list of targets,
1975  *               and a suitable target for rich text is included,
1976  *               otherwise %FALSE.
1977  *
1978  * Since: 2.10
1979  **/
1980 gboolean
1981 gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data,
1982                                               GtkTextBuffer    *buffer)
1983 {
1984   GdkAtom *targets;
1985   gint n_targets;
1986   gboolean result = FALSE;
1987
1988   g_return_val_if_fail (selection_data != NULL, FALSE);
1989   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
1990
1991   init_atoms ();
1992
1993   if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1994     {
1995       result = gtk_targets_include_rich_text (targets, n_targets, buffer);
1996       g_free (targets);
1997     }
1998
1999   return result;
2000 }
2001
2002 /**
2003  * gtk_targets_include_image:
2004  * @targets: an array of #GdkAtom<!-- -->s
2005  * @n_targets: the length of @targets
2006  * @writable: whether to accept only targets for which GTK+ knows
2007  *   how to convert a pixbuf into the format
2008  * 
2009  * Determines if any of the targets in @targets can be used to
2010  * provide a #GdkPixbuf.
2011  * 
2012  * Return value: %TRUE if @targets include a suitable target for images,
2013  *   otherwise %FALSE.
2014  *
2015  * Since: 2.10
2016  **/
2017 gboolean 
2018 gtk_targets_include_image (GdkAtom *targets,
2019                            gint     n_targets,
2020                            gboolean writable)
2021 {
2022   GtkTargetList *list;
2023   GList *l;
2024   gint i;
2025   gboolean result = FALSE;
2026
2027   g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2028
2029   list = gtk_target_list_new (NULL, 0);
2030   gtk_target_list_add_image_targets (list, 0, writable);
2031   for (i = 0; i < n_targets && !result; i++)
2032     {
2033       for (l = list->list; l; l = l->next)
2034         {
2035           GtkTargetPair *pair = (GtkTargetPair *)l->data;
2036           if (pair->target == targets[i])
2037             {
2038               result = TRUE;
2039               break;
2040             }
2041         }
2042     }
2043   gtk_target_list_unref (list);
2044
2045   return result;
2046 }
2047                                     
2048 /**
2049  * gtk_selection_data_targets_include_image:
2050  * @selection_data: a #GtkSelectionData object
2051  * @writable: whether to accept only targets for which GTK+ knows
2052  *   how to convert a pixbuf into the format
2053  * 
2054  * Given a #GtkSelectionData object holding a list of targets,
2055  * determines if any of the targets in @targets can be used to
2056  * provide a #GdkPixbuf.
2057  * 
2058  * Return value: %TRUE if @selection_data holds a list of targets,
2059  *   and a suitable target for images is included, otherwise %FALSE.
2060  *
2061  * Since: 2.6
2062  **/
2063 gboolean 
2064 gtk_selection_data_targets_include_image (GtkSelectionData *selection_data,
2065                                           gboolean          writable)
2066 {
2067   GdkAtom *targets;
2068   gint n_targets;
2069   gboolean result = FALSE;
2070
2071   g_return_val_if_fail (selection_data != NULL, FALSE);
2072
2073   init_atoms ();
2074
2075   if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2076     {
2077       result = gtk_targets_include_image (targets, n_targets, writable);
2078       g_free (targets);
2079     }
2080
2081   return result;
2082 }
2083
2084 /**
2085  * gtk_targets_include_uri:
2086  * @targets: an array of #GdkAtom<!-- -->s
2087  * @n_targets: the length of @targets
2088  * 
2089  * Determines if any of the targets in @targets can be used to
2090  * provide an uri list.
2091  * 
2092  * Return value: %TRUE if @targets include a suitable target for uri lists,
2093  *   otherwise %FALSE.
2094  *
2095  * Since: 2.10
2096  **/
2097 gboolean 
2098 gtk_targets_include_uri (GdkAtom *targets,
2099                          gint     n_targets)
2100 {
2101   gint i;
2102   gboolean result = FALSE;
2103
2104   g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
2105
2106   /* Keep in sync with gtk_target_list_add_uri_targets()
2107    */
2108
2109   init_atoms ();
2110
2111   for (i = 0; i < n_targets; i++)
2112     {
2113       if (targets[i] == text_uri_list_atom)
2114         {
2115           result = TRUE;
2116           break;
2117         }
2118     }
2119   
2120   return result;
2121 }
2122
2123 /**
2124  * gtk_selection_data_targets_include_uri:
2125  * @selection_data: a #GtkSelectionData object
2126  * 
2127  * Given a #GtkSelectionData object holding a list of targets,
2128  * determines if any of the targets in @targets can be used to
2129  * provide a list or URIs.
2130  * 
2131  * Return value: %TRUE if @selection_data holds a list of targets,
2132  *   and a suitable target for URI lists is included, otherwise %FALSE.
2133  *
2134  * Since: 2.10
2135  **/
2136 gboolean
2137 gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data)
2138 {
2139   GdkAtom *targets;
2140   gint n_targets;
2141   gboolean result = FALSE;
2142
2143   g_return_val_if_fail (selection_data != NULL, FALSE);
2144
2145   init_atoms ();
2146
2147   if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
2148     {
2149       result = gtk_targets_include_uri (targets, n_targets);
2150       g_free (targets);
2151     }
2152
2153   return result;
2154 }
2155
2156           
2157 /*************************************************************
2158  * gtk_selection_init:
2159  *     Initialize local variables
2160  *   arguments:
2161  *     
2162  *   results:
2163  *************************************************************/
2164
2165 static void
2166 gtk_selection_init (void)
2167 {
2168   gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
2169   gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
2170   gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
2171   gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
2172
2173   initialize = FALSE;
2174 }
2175
2176 /**
2177  * gtk_selection_clear:
2178  * @widget: a #GtkWidget
2179  * @event: the event
2180  * 
2181  * The default handler for the GtkWidget::selection_clear_event
2182  * signal. 
2183  * 
2184  * Return value: %TRUE if the event was handled, otherwise false
2185  * 
2186  * Since: 2.2
2187  *
2188  * Deprecated: 2.4: Instead of calling this function, chain up from
2189  * your selection_clear_event handler. Calling this function
2190  * from any other context is illegal. 
2191  **/
2192 gboolean
2193 gtk_selection_clear (GtkWidget         *widget,
2194                      GdkEventSelection *event)
2195 {
2196   /* Note that we filter clear events in gdkselection-x11.c, so
2197    * that we only will get here if the clear event actually
2198    * represents a change that we didn't do ourself.
2199    */
2200   GList *tmp_list;
2201   GtkSelectionInfo *selection_info = NULL;
2202   
2203   tmp_list = current_selections;
2204   while (tmp_list)
2205     {
2206       selection_info = (GtkSelectionInfo *)tmp_list->data;
2207       
2208       if ((selection_info->selection == event->selection) &&
2209           (selection_info->widget == widget))
2210         break;
2211       
2212       tmp_list = tmp_list->next;
2213     }
2214   
2215   if (tmp_list)
2216     {
2217       current_selections = g_list_remove_link (current_selections, tmp_list);
2218       g_list_free (tmp_list);
2219       g_slice_free (GtkSelectionInfo, selection_info);
2220     }
2221   
2222   return TRUE;
2223 }
2224
2225
2226 /*************************************************************
2227  * _gtk_selection_request:
2228  *     Handler for "selection_request_event" 
2229  *   arguments:
2230  *     widget:
2231  *     event:
2232  *   results:
2233  *************************************************************/
2234
2235 gboolean
2236 _gtk_selection_request (GtkWidget *widget,
2237                         GdkEventSelection *event)
2238 {
2239   GdkDisplay *display = gtk_widget_get_display (widget);
2240   GtkIncrInfo *info;
2241   GList *tmp_list;
2242   int i;
2243   gulong selection_max_size;
2244
2245   if (initialize)
2246     gtk_selection_init ();
2247   
2248   selection_max_size = GTK_SELECTION_MAX_SIZE (display);
2249
2250   /* Check if we own selection */
2251   
2252   tmp_list = current_selections;
2253   while (tmp_list)
2254     {
2255       GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
2256       
2257       if ((selection_info->selection == event->selection) &&
2258           (selection_info->widget == widget))
2259         break;
2260       
2261       tmp_list = tmp_list->next;
2262     }
2263   
2264   if (tmp_list == NULL)
2265     return FALSE;
2266   
2267   info = g_slice_new (GtkIncrInfo);
2268
2269   g_object_ref (widget);
2270   
2271   info->selection = event->selection;
2272   info->num_incrs = 0;
2273   
2274   /* Create GdkWindow structure for the requestor */
2275   
2276   info->requestor = gdk_window_lookup_for_display (display,
2277                                                    event->requestor);
2278   if (!info->requestor)
2279     info->requestor = gdk_window_foreign_new_for_display (display,
2280                                                           event->requestor);
2281   
2282   /* Determine conversions we need to perform */
2283   
2284   if (event->target == gtk_selection_atoms[MULTIPLE])
2285     {
2286       GdkAtom  type;
2287       guchar  *mult_atoms;
2288       gint     format;
2289       gint     length;
2290       
2291       mult_atoms = NULL;
2292       
2293       gdk_error_trap_push ();
2294       if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
2295                              0, selection_max_size, FALSE,
2296                              &type, &format, &length, &mult_atoms))
2297         {
2298           gdk_selection_send_notify_for_display (display,
2299                                                  event->requestor, 
2300                                                  event->selection,
2301                                                  event->target, 
2302                                                  GDK_NONE, 
2303                                                  event->time);
2304           g_free (mult_atoms);
2305           g_slice_free (GtkIncrInfo, info);
2306           gdk_error_trap_pop ();
2307           return TRUE;
2308         }
2309       gdk_error_trap_pop ();
2310
2311       /* This is annoying; the ICCCM doesn't specify the property type
2312        * used for the property contents, so the autoconversion for
2313        * ATOM / ATOM_PAIR in GDK doesn't work properly.
2314        */
2315 #ifdef GDK_WINDOWING_X11
2316       if (type != GDK_SELECTION_TYPE_ATOM &&
2317           type != gdk_atom_intern_static_string ("ATOM_PAIR"))
2318         {
2319           info->num_conversions = length / (2*sizeof (glong));
2320           info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2321           
2322           for (i=0; i<info->num_conversions; i++)
2323             {
2324               info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
2325                                                                                ((glong *)mult_atoms)[2*i]);
2326               info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
2327                                                                                  ((glong *)mult_atoms)[2*i + 1]);
2328             }
2329
2330           g_free (mult_atoms);
2331         }
2332       else
2333 #endif
2334         {
2335           info->num_conversions = length / (2*sizeof (GdkAtom));
2336           info->conversions = g_new (GtkIncrConversion, info->num_conversions);
2337           
2338           for (i=0; i<info->num_conversions; i++)
2339             {
2340               info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
2341               info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
2342             }
2343
2344           g_free (mult_atoms);
2345         }
2346     }
2347   else                          /* only a single conversion */
2348     {
2349       info->conversions = g_new (GtkIncrConversion, 1);
2350       info->num_conversions = 1;
2351       info->conversions[0].target = event->target;
2352       info->conversions[0].property = event->property;
2353     }
2354   
2355   /* Loop through conversions and determine which of these are big
2356      enough to require doing them via INCR */
2357   for (i=0; i<info->num_conversions; i++)
2358     {
2359       GtkSelectionData data;
2360       glong items;
2361       
2362       data.selection = event->selection;
2363       data.target = info->conversions[i].target;
2364       data.data = NULL;
2365       data.length = -1;
2366       data.display = gtk_widget_get_display (widget);
2367       
2368 #ifdef DEBUG_SELECTION
2369       g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
2370                  event->selection, 
2371                  info->conversions[i].target,
2372                  gdk_atom_name (info->conversions[i].target),
2373                  event->requestor, info->conversions[i].property);
2374 #endif
2375       
2376       gtk_selection_invoke_handler (widget, &data, event->time);
2377       
2378       if (data.length < 0)
2379         {
2380           info->conversions[i].property = GDK_NONE;
2381           continue;
2382         }
2383       
2384       g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2385       
2386       items = data.length / gtk_selection_bytes_per_item (data.format);
2387       
2388       if (data.length > selection_max_size)
2389         {
2390           /* Sending via INCR */
2391 #ifdef DEBUG_SELECTION
2392           g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2393                      data.length, selection_max_size);
2394 #endif
2395           
2396           info->conversions[i].offset = 0;
2397           info->conversions[i].data = data;
2398           info->num_incrs++;
2399           
2400           gdk_property_change (info->requestor, 
2401                                info->conversions[i].property,
2402                                gtk_selection_atoms[INCR],
2403                                32,
2404                                GDK_PROP_MODE_REPLACE,
2405                                (guchar *)&items, 1);
2406         }
2407       else
2408         {
2409           info->conversions[i].offset = -1;
2410           
2411           gdk_property_change (info->requestor, 
2412                                info->conversions[i].property,
2413                                data.type,
2414                                data.format,
2415                                GDK_PROP_MODE_REPLACE,
2416                                data.data, items);
2417           
2418           g_free (data.data);
2419         }
2420     }
2421   
2422   /* If we have some INCR's, we need to send the rest of the data in
2423      a callback */
2424   
2425   if (info->num_incrs > 0)
2426     {
2427       /* FIXME: this could be dangerous if window doesn't still
2428          exist */
2429       
2430 #ifdef DEBUG_SELECTION
2431       g_message ("Starting INCR...");
2432 #endif
2433       
2434       gdk_window_set_events (info->requestor,
2435                              gdk_window_get_events (info->requestor) |
2436                              GDK_PROPERTY_CHANGE_MASK);
2437       current_incrs = g_list_append (current_incrs, info);
2438       gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2439     }
2440   
2441   /* If it was a MULTIPLE request, set the property to indicate which
2442      conversions succeeded */
2443   if (event->target == gtk_selection_atoms[MULTIPLE])
2444     {
2445       GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2446       for (i = 0; i < info->num_conversions; i++)
2447         {
2448           mult_atoms[2*i] = info->conversions[i].target;
2449           mult_atoms[2*i+1] = info->conversions[i].property;
2450         }
2451       
2452       gdk_property_change (info->requestor, event->property,
2453                            gdk_atom_intern_static_string ("ATOM_PAIR"), 32, 
2454                            GDK_PROP_MODE_REPLACE,
2455                            (guchar *)mult_atoms, 2*info->num_conversions);
2456       g_free (mult_atoms);
2457     }
2458
2459   if (info->num_conversions == 1 &&
2460       info->conversions[0].property == GDK_NONE)
2461     {
2462       /* Reject the entire conversion */
2463       gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2464                                              event->requestor, 
2465                                              event->selection, 
2466                                              event->target, 
2467                                              GDK_NONE, 
2468                                              event->time);
2469     }
2470   else
2471     {
2472       gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2473                                              event->requestor, 
2474                                              event->selection,
2475                                              event->target,
2476                                              event->property, 
2477                                              event->time);
2478     }
2479
2480   if (info->num_incrs == 0)
2481     {
2482       g_free (info->conversions);
2483       g_slice_free (GtkIncrInfo, info);
2484     }
2485
2486   g_object_unref (widget);
2487   
2488   return TRUE;
2489 }
2490
2491 /*************************************************************
2492  * _gtk_selection_incr_event:
2493  *     Called whenever an PropertyNotify event occurs for an 
2494  *     GdkWindow with user_data == NULL. These will be notifications
2495  *     that a window we are sending the selection to via the
2496  *     INCR protocol has deleted a property and is ready for
2497  *     more data.
2498  *
2499  *   arguments:
2500  *     window:  the requestor window
2501  *     event:   the property event structure
2502  *
2503  *   results:
2504  *************************************************************/
2505
2506 gboolean
2507 _gtk_selection_incr_event (GdkWindow       *window,
2508                            GdkEventProperty *event)
2509 {
2510   GList *tmp_list;
2511   GtkIncrInfo *info = NULL;
2512   gint num_bytes;
2513   guchar *buffer;
2514   gulong selection_max_size;
2515   
2516   int i;
2517   
2518   if (event->state != GDK_PROPERTY_DELETE)
2519     return FALSE;
2520   
2521 #ifdef DEBUG_SELECTION
2522   g_message ("PropertyDelete, property %ld", event->atom);
2523 #endif
2524
2525   selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_drawable_get_display (window));  
2526
2527   /* Now find the appropriate ongoing INCR */
2528   tmp_list = current_incrs;
2529   while (tmp_list)
2530     {
2531       info = (GtkIncrInfo *)tmp_list->data;
2532       if (info->requestor == event->window)
2533         break;
2534       
2535       tmp_list = tmp_list->next;
2536     }
2537   
2538   if (tmp_list == NULL)
2539     return FALSE;
2540   
2541   /* Find out which target this is for */
2542   for (i=0; i<info->num_conversions; i++)
2543     {
2544       if (info->conversions[i].property == event->atom &&
2545           info->conversions[i].offset != -1)
2546         {
2547           int bytes_per_item;
2548           
2549           info->idle_time = 0;
2550           
2551           if (info->conversions[i].offset == -2) /* only the last 0-length
2552                                                     piece*/
2553             {
2554               num_bytes = 0;
2555               buffer = NULL;
2556             }
2557           else
2558             {
2559               num_bytes = info->conversions[i].data.length -
2560                 info->conversions[i].offset;
2561               buffer = info->conversions[i].data.data + 
2562                 info->conversions[i].offset;
2563               
2564               if (num_bytes > selection_max_size)
2565                 {
2566                   num_bytes = selection_max_size;
2567                   info->conversions[i].offset += selection_max_size;
2568                 }
2569               else
2570                 info->conversions[i].offset = -2;
2571             }
2572 #ifdef DEBUG_SELECTION
2573           g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2574                      num_bytes, info->conversions[i].offset, 
2575                      GDK_WINDOW_XWINDOW(info->requestor), event->atom);
2576 #endif
2577
2578           bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2579           gdk_property_change (info->requestor, event->atom,
2580                                info->conversions[i].data.type,
2581                                info->conversions[i].data.format,
2582                                GDK_PROP_MODE_REPLACE,
2583                                buffer,
2584                                num_bytes / bytes_per_item);
2585           
2586           if (info->conversions[i].offset == -2)
2587             {
2588               g_free (info->conversions[i].data.data);
2589               info->conversions[i].data.data = NULL;
2590             }
2591           
2592           if (num_bytes == 0)
2593             {
2594               info->num_incrs--;
2595               info->conversions[i].offset = -1;
2596             }
2597         }
2598     }
2599   
2600   /* Check if we're finished with all the targets */
2601   
2602   if (info->num_incrs == 0)
2603     {
2604       current_incrs = g_list_remove_link (current_incrs, tmp_list);
2605       g_list_free (tmp_list);
2606       /* Let the timeout free it */
2607     }
2608   
2609   return TRUE;
2610 }
2611
2612 /*************************************************************
2613  * gtk_selection_incr_timeout:
2614  *     Timeout callback for the sending portion of the INCR
2615  *     protocol
2616  *   arguments:
2617  *     info:    Information about this incr
2618  *   results:
2619  *************************************************************/
2620
2621 static gint
2622 gtk_selection_incr_timeout (GtkIncrInfo *info)
2623 {
2624   GList *tmp_list;
2625   gboolean retval;
2626
2627   /* Determine if retrieval has finished by checking if it still in
2628      list of pending retrievals */
2629   
2630   tmp_list = current_incrs;
2631   while (tmp_list)
2632     {
2633       if (info == (GtkIncrInfo *)tmp_list->data)
2634         break;
2635       tmp_list = tmp_list->next;
2636     }
2637   
2638   /* If retrieval is finished */
2639   if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2640     {
2641       if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2642         {
2643           current_incrs = g_list_remove_link (current_incrs, tmp_list);
2644           g_list_free (tmp_list);
2645         }
2646       
2647       g_free (info->conversions);
2648       /* FIXME: we should check if requestor window is still in use,
2649          and if not, remove it? */
2650       
2651       g_slice_free (GtkIncrInfo, info);
2652       
2653       retval =  FALSE;          /* remove timeout */
2654     }
2655   else
2656     {
2657       info->idle_time++;
2658       
2659       retval = TRUE;            /* timeout will happen again */
2660     }
2661   
2662   return retval;
2663 }
2664
2665 /*************************************************************
2666  * _gtk_selection_notify:
2667  *     Handler for "selection-notify-event" signals on windows
2668  *     where a retrieval is currently in process. The selection
2669  *     owner has responded to our conversion request.
2670  *   arguments:
2671  *     widget:          Widget getting signal
2672  *     event:           Selection event structure
2673  *     info:            Information about this retrieval
2674  *   results:
2675  *     was event handled?
2676  *************************************************************/
2677
2678 gboolean
2679 _gtk_selection_notify (GtkWidget               *widget,
2680                        GdkEventSelection *event)
2681 {
2682   GList *tmp_list;
2683   GtkRetrievalInfo *info = NULL;
2684   guchar  *buffer = NULL;
2685   gint length;
2686   GdkAtom type;
2687   gint    format;
2688   
2689 #ifdef DEBUG_SELECTION
2690   g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2691              event->selection, event->target, event->property);
2692 #endif
2693   
2694   tmp_list = current_retrievals;
2695   while (tmp_list)
2696     {
2697       info = (GtkRetrievalInfo *)tmp_list->data;
2698       if (info->widget == widget && info->selection == event->selection)
2699         break;
2700       tmp_list = tmp_list->next;
2701     }
2702   
2703   if (!tmp_list)                /* no retrieval in progress */
2704     return FALSE;
2705
2706   if (event->property != GDK_NONE)
2707     length = gdk_selection_property_get (widget->window, &buffer, 
2708                                          &type, &format);
2709   else
2710     length = 0; /* silence gcc */
2711   
2712   if (event->property == GDK_NONE || buffer == NULL)
2713     {
2714       current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2715       g_list_free (tmp_list);
2716       /* structure will be freed in timeout */
2717       gtk_selection_retrieval_report (info,
2718                                       GDK_NONE, 0, NULL, -1, event->time);
2719       
2720       return TRUE;
2721     }
2722   
2723   if (type == gtk_selection_atoms[INCR])
2724     {
2725       /* The remainder of the selection will come through PropertyNotify
2726          events */
2727
2728       info->notify_time = event->time;
2729       info->idle_time = 0;
2730       info->offset = 0;         /* Mark as OK to proceed */
2731       gdk_window_set_events (widget->window,
2732                              gdk_window_get_events (widget->window)
2733                              | GDK_PROPERTY_CHANGE_MASK);
2734     }
2735   else
2736     {
2737       /* We don't delete the info structure - that will happen in timeout */
2738       current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2739       g_list_free (tmp_list);
2740       
2741       info->offset = length;
2742       gtk_selection_retrieval_report (info,
2743                                       type, format, 
2744                                       buffer, length, event->time);
2745     }
2746   
2747   gdk_property_delete (widget->window, event->property);
2748   
2749   g_free (buffer);
2750   
2751   return TRUE;
2752 }
2753
2754 /*************************************************************
2755  * _gtk_selection_property_notify:
2756  *     Handler for "property-notify-event" signals on windows
2757  *     where a retrieval is currently in process. The selection
2758  *     owner has added more data.
2759  *   arguments:
2760  *     widget:          Widget getting signal
2761  *     event:           Property event structure
2762  *     info:            Information about this retrieval
2763  *   results:
2764  *     was event handled?
2765  *************************************************************/
2766
2767 gboolean
2768 _gtk_selection_property_notify (GtkWidget       *widget,
2769                                 GdkEventProperty *event)
2770 {
2771   GList *tmp_list;
2772   GtkRetrievalInfo *info = NULL;
2773   guchar *new_buffer;
2774   int length;
2775   GdkAtom type;
2776   gint    format;
2777   
2778   g_return_val_if_fail (widget != NULL, FALSE);
2779   g_return_val_if_fail (event != NULL, FALSE);
2780
2781 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2782   if ((event->state != GDK_PROPERTY_NEW_VALUE) ||  /* property was deleted */
2783       (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2784 #endif
2785     return FALSE;
2786   
2787 #ifdef DEBUG_SELECTION
2788   g_message ("PropertyNewValue, property %ld",
2789              event->atom);
2790 #endif
2791   
2792   tmp_list = current_retrievals;
2793   while (tmp_list)
2794     {
2795       info = (GtkRetrievalInfo *)tmp_list->data;
2796       if (info->widget == widget)
2797         break;
2798       tmp_list = tmp_list->next;
2799     }
2800   
2801   if (!tmp_list)                /* No retrieval in progress */
2802     return FALSE;
2803   
2804   if (info->offset < 0)         /* We haven't got the SelectionNotify
2805                                    for this retrieval yet */
2806     return FALSE;
2807   
2808   info->idle_time = 0;
2809   
2810   length = gdk_selection_property_get (widget->window, &new_buffer, 
2811                                        &type, &format);
2812   gdk_property_delete (widget->window, event->atom);
2813   
2814   /* We could do a lot better efficiency-wise by paying attention to
2815      what length was sent in the initial INCR transaction, instead of
2816      doing memory allocation at every step. But its only guaranteed to
2817      be a _lower bound_ (pretty useless!) */
2818   
2819   if (length == 0 || type == GDK_NONE)          /* final zero length portion */
2820     {
2821       /* Info structure will be freed in timeout */
2822       current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2823       g_list_free (tmp_list);
2824       gtk_selection_retrieval_report (info,
2825                                       type, format, 
2826                                       (type == GDK_NONE) ?  NULL : info->buffer,
2827                                       (type == GDK_NONE) ?  -1 : info->offset,
2828                                       info->notify_time);
2829     }
2830   else                          /* append on newly arrived data */
2831     {
2832       if (!info->buffer)
2833         {
2834 #ifdef DEBUG_SELECTION
2835           g_message ("Start - Adding %d bytes at offset 0",
2836                      length);
2837 #endif
2838           info->buffer = new_buffer;
2839           info->offset = length;
2840         }
2841       else
2842         {
2843           
2844 #ifdef DEBUG_SELECTION
2845           g_message ("Appending %d bytes at offset %d",
2846                      length,info->offset);
2847 #endif
2848           /* We copy length+1 bytes to preserve guaranteed null termination */
2849           info->buffer = g_realloc (info->buffer, info->offset+length+1);
2850           memcpy (info->buffer + info->offset, new_buffer, length+1);
2851           info->offset += length;
2852           g_free (new_buffer);
2853         }
2854     }
2855   
2856   return TRUE;
2857 }
2858
2859 /*************************************************************
2860  * gtk_selection_retrieval_timeout:
2861  *     Timeout callback while receiving a selection.
2862  *   arguments:
2863  *     info:    Information about this retrieval
2864  *   results:
2865  *************************************************************/
2866
2867 static gboolean
2868 gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
2869 {
2870   GList *tmp_list;
2871   gboolean retval;
2872
2873   /* Determine if retrieval has finished by checking if it still in
2874      list of pending retrievals */
2875   
2876   tmp_list = current_retrievals;
2877   while (tmp_list)
2878     {
2879       if (info == (GtkRetrievalInfo *)tmp_list->data)
2880         break;
2881       tmp_list = tmp_list->next;
2882     }
2883   
2884   /* If retrieval is finished */
2885   if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2886     {
2887       if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2888         {
2889           current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2890           g_list_free (tmp_list);
2891           gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1, GDK_CURRENT_TIME);
2892         }
2893       
2894       g_free (info->buffer);
2895       g_slice_free (GtkRetrievalInfo, info);
2896       
2897       retval =  FALSE;          /* remove timeout */
2898     }
2899   else
2900     {
2901       info->idle_time++;
2902       
2903       retval =  TRUE;           /* timeout will happen again */
2904     }
2905
2906   return retval;
2907 }
2908
2909 /*************************************************************
2910  * gtk_selection_retrieval_report:
2911  *     Emits a "selection-received" signal.
2912  *   arguments:
2913  *     info:      information about the retrieval that completed
2914  *     buffer:    buffer containing data (NULL => errror)
2915  *     time:      timestamp for data in buffer
2916  *   results:
2917  *************************************************************/
2918
2919 static void
2920 gtk_selection_retrieval_report (GtkRetrievalInfo *info,
2921                                 GdkAtom type, gint format, 
2922                                 guchar *buffer, gint length,
2923                                 guint32 time)
2924 {
2925   GtkSelectionData data;
2926   
2927   data.selection = info->selection;
2928   data.target = info->target;
2929   data.type = type;
2930   data.format = format;
2931   
2932   data.length = length;
2933   data.data = buffer;
2934   data.display = gtk_widget_get_display (info->widget);
2935   
2936   g_signal_emit_by_name (info->widget,
2937                          "selection-received", 
2938                          &data, time);
2939 }
2940
2941 /*************************************************************
2942  * gtk_selection_invoke_handler:
2943  *     Finds and invokes handler for specified
2944  *     widget/selection/target combination, calls 
2945  *     gtk_selection_default_handler if none exists.
2946  *
2947  *   arguments:
2948  *     widget:      selection owner
2949  *     data:        selection data [INOUT]
2950  *     time:        time from requeset
2951  *     
2952  *   results:
2953  *     Number of bytes written to buffer, -1 if error
2954  *************************************************************/
2955
2956 static void
2957 gtk_selection_invoke_handler (GtkWidget        *widget,
2958                               GtkSelectionData *data,
2959                               guint             time)
2960 {
2961   GtkTargetList *target_list;
2962   guint info;
2963   
2964
2965   g_return_if_fail (widget != NULL);
2966
2967   target_list = gtk_selection_target_list_get (widget, data->selection);
2968   if (target_list && 
2969       gtk_target_list_find (target_list, data->target, &info))
2970     {
2971       g_signal_emit_by_name (widget,
2972                              "selection-get",
2973                              data,
2974                              info, time);
2975     }
2976   else
2977     gtk_selection_default_handler (widget, data);
2978 }
2979
2980 /*************************************************************
2981  * gtk_selection_default_handler:
2982  *     Handles some default targets that exist for any widget
2983  *     If it can't fit results into buffer, returns -1. This
2984  *     won't happen in any conceivable case, since it would
2985  *     require 1000 selection targets!
2986  *
2987  *   arguments:
2988  *     widget:      selection owner
2989  *     data:        selection data [INOUT]
2990  *
2991  *************************************************************/
2992
2993 static void
2994 gtk_selection_default_handler (GtkWidget        *widget,
2995                                GtkSelectionData *data)
2996 {
2997   if (data->target == gtk_selection_atoms[TIMESTAMP])
2998     {
2999       /* Time which was used to obtain selection */
3000       GList *tmp_list;
3001       GtkSelectionInfo *selection_info;
3002       
3003       tmp_list = current_selections;
3004       while (tmp_list)
3005         {
3006           selection_info = (GtkSelectionInfo *)tmp_list->data;
3007           if ((selection_info->widget == widget) &&
3008               (selection_info->selection == data->selection))
3009             {
3010               gulong time = selection_info->time;
3011
3012               gtk_selection_data_set (data,
3013                                       GDK_SELECTION_TYPE_INTEGER,
3014                                       32,
3015                                       (guchar *)&time,
3016                                       sizeof (time));
3017               return;
3018             }
3019           
3020           tmp_list = tmp_list->next;
3021         }
3022       
3023       data->length = -1;
3024     }
3025   else if (data->target == gtk_selection_atoms[TARGETS])
3026     {
3027       /* List of all targets supported for this widget/selection pair */
3028       GdkAtom *p;
3029       guint count;
3030       GList *tmp_list;
3031       GtkTargetList *target_list;
3032       GtkTargetPair *pair;
3033       
3034       target_list = gtk_selection_target_list_get (widget,
3035                                                    data->selection);
3036       count = g_list_length (target_list->list) + 3;
3037       
3038       data->type = GDK_SELECTION_TYPE_ATOM;
3039       data->format = 32;
3040       data->length = count * sizeof (GdkAtom);
3041
3042       /* selection data is always terminated by a trailing \0
3043        */
3044       p = g_malloc (data->length + 1);
3045       data->data = (guchar *)p;
3046       data->data[data->length] = '\0';
3047       
3048       *p++ = gtk_selection_atoms[TIMESTAMP];
3049       *p++ = gtk_selection_atoms[TARGETS];
3050       *p++ = gtk_selection_atoms[MULTIPLE];
3051       
3052       tmp_list = target_list->list;
3053       while (tmp_list)
3054         {
3055           pair = (GtkTargetPair *)tmp_list->data;
3056           *p++ = pair->target;
3057           
3058           tmp_list = tmp_list->next;
3059         }
3060     }
3061   else
3062     {
3063       data->length = -1;
3064     }
3065 }
3066
3067
3068 /**
3069  * gtk_selection_data_copy:
3070  * @data: a pointer to a #GtkSelectionData structure.
3071  * 
3072  * Makes a copy of a #GtkSelectionData structure and its data.
3073  * 
3074  * Return value: a pointer to a copy of @data.
3075  **/
3076 GtkSelectionData*
3077 gtk_selection_data_copy (GtkSelectionData *data)
3078 {
3079   GtkSelectionData *new_data;
3080   
3081   g_return_val_if_fail (data != NULL, NULL);
3082   
3083   new_data = g_slice_new (GtkSelectionData);
3084   *new_data = *data;
3085
3086   if (data->data)
3087     {
3088       new_data->data = g_malloc (data->length + 1);
3089       memcpy (new_data->data, data->data, data->length + 1);
3090     }
3091   
3092   return new_data;
3093 }
3094
3095 /**
3096  * gtk_selection_data_free:
3097  * @data: a pointer to a #GtkSelectionData structure.
3098  * 
3099  * Frees a #GtkSelectionData structure returned from
3100  * gtk_selection_data_copy().
3101  **/
3102 void
3103 gtk_selection_data_free (GtkSelectionData *data)
3104 {
3105   g_return_if_fail (data != NULL);
3106   
3107   g_free (data->data);
3108   
3109   g_slice_free (GtkSelectionData, data);
3110 }
3111
3112 GType
3113 gtk_selection_data_get_type (void)
3114 {
3115   static GType our_type = 0;
3116   
3117   if (our_type == 0)
3118     our_type = g_boxed_type_register_static (I_("GtkSelectionData"),
3119                                              (GBoxedCopyFunc) gtk_selection_data_copy,
3120                                              (GBoxedFreeFunc) gtk_selection_data_free);
3121
3122   return our_type;
3123 }
3124
3125 GType
3126 gtk_target_list_get_type (void)
3127 {
3128   static GType our_type = 0;
3129
3130   if (our_type == 0)
3131     our_type = g_boxed_type_register_static (I_("GtkTargetList"),
3132                                              (GBoxedCopyFunc) gtk_target_list_ref,
3133                                              (GBoxedFreeFunc) gtk_target_list_unref);
3134
3135   return our_type;
3136 }
3137
3138 static int 
3139 gtk_selection_bytes_per_item (gint format)
3140 {
3141   switch (format)
3142     {
3143     case 8:
3144       return sizeof (char);
3145       break;
3146     case 16:
3147       return sizeof (short);
3148       break;
3149     case 32:
3150       return sizeof (long);
3151       break;
3152     default:
3153       g_assert_not_reached();
3154     }
3155   return 0;
3156 }
3157
3158 #define __GTK_SELECTION_C__
3159 #include "gtkaliasdef.c"