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