1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
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
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.
31 * By Owen Taylor <owt1@cornell.edu> 8/16/97
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 ....)
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 ... */
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/.
60 #include "gtkselection.h"
62 #include "gdk-pixbuf/gdk-pixbuf.h"
64 #ifdef GDK_WINDOWING_X11
68 #ifdef GDK_WINDOWING_WIN32
69 #include "win32/gdkwin32.h"
74 #undef DEBUG_SELECTION
76 /* Maximum size of a sent chunk, in bytes. Also the default size of
78 #ifdef GDK_WINDOWING_X11
79 #define GTK_SELECTION_MAX_SIZE(display) \
81 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
82 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
83 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
85 /* No chunks on Win32 */
86 #define GTK_SELECTION_MAX_SIZE(display) G_MAXINT
89 #define IDLE_ABORT_TIME 30
99 typedef struct _GtkSelectionInfo GtkSelectionInfo;
100 typedef struct _GtkIncrConversion GtkIncrConversion;
101 typedef struct _GtkIncrInfo GtkIncrInfo;
102 typedef struct _GtkRetrievalInfo GtkRetrievalInfo;
104 struct _GtkSelectionInfo
107 GtkWidget *widget; /* widget that owns selection */
108 guint32 time; /* time used to acquire selection */
109 GdkDisplay *display; /* needed in gtk_selection_remove_all */
112 struct _GtkIncrConversion
114 GdkAtom target; /* Requested target */
115 GdkAtom property; /* Property to store in */
116 GtkSelectionData data; /* The data being supplied */
117 gint offset; /* Current offset in sent selection.
119 * -2 => Only the final (empty) portion
125 GdkWindow *requestor; /* Requestor window - we create a GdkWindow
126 so we can receive events */
127 GdkAtom selection; /* Selection we're sending */
129 GtkIncrConversion *conversions; /* Information about requested conversions -
130 * With MULTIPLE requests (benighted 1980's
131 * hardware idea), there can be more than
133 gint num_conversions;
134 gint num_incrs; /* number of remaining INCR style transactions */
139 struct _GtkRetrievalInfo
142 GdkAtom selection; /* Selection being retrieved. */
143 GdkAtom target; /* Form of selection that we requested */
144 guint32 idle_time; /* Number of seconds since we last heard
145 from selection owner */
146 guchar *buffer; /* Buffer in which to accumulate results */
147 gint offset; /* Current offset in buffer, -1 indicates
149 guint32 notify_time; /* Timestamp from SelectionNotify */
152 /* Local Functions */
153 static void gtk_selection_init (void);
154 static gint gtk_selection_incr_timeout (GtkIncrInfo *info);
155 static gint gtk_selection_retrieval_timeout (GtkRetrievalInfo *info);
156 static void gtk_selection_retrieval_report (GtkRetrievalInfo *info,
162 static void gtk_selection_invoke_handler (GtkWidget *widget,
163 GtkSelectionData *data,
165 static void gtk_selection_default_handler (GtkWidget *widget,
166 GtkSelectionData *data);
167 static int gtk_selection_bytes_per_item (gint format);
170 static gint initialize = TRUE;
171 static GList *current_retrievals = NULL;
172 static GList *current_incrs = NULL;
173 static GList *current_selections = NULL;
175 static GdkAtom gtk_selection_atoms[LAST_ATOM];
176 static const char gtk_selection_handler_key[] = "gtk-selection-handlers";
188 * gtk_target_list_new:
189 * @targets: Pointer to an array of #GtkTargetEntry
190 * @ntargets: number of entries in @targets.
192 * Creates a new #GtkTargetList from an array of #GtkTargetEntry.
194 * Return value: the new #GtkTargetList.
197 gtk_target_list_new (const GtkTargetEntry *targets,
200 GtkTargetList *result = g_new (GtkTargetList, 1);
202 result->ref_count = 1;
205 gtk_target_list_add_table (result, targets, ntargets);
211 * gtk_target_list_ref:
212 * @list: a #GtkTargetList
214 * Increases the reference count of a #GtkTargetList by one.
218 gtk_target_list_ref (GtkTargetList *list)
220 g_return_if_fail (list != NULL);
226 * gtk_target_list_unref:
227 * @list: a #GtkTargetList
229 * Decreases the reference count of a #GtkTargetList by one.
230 * If the resulting reference count is zero, frees the list.
233 gtk_target_list_unref (GtkTargetList *list)
235 g_return_if_fail (list != NULL);
236 g_return_if_fail (list->ref_count > 0);
239 if (list->ref_count == 0)
241 GList *tmp_list = list->list;
244 GtkTargetPair *pair = tmp_list->data;
247 tmp_list = tmp_list->next;
250 g_list_free (list->list);
256 * gtk_target_list_add:
257 * @list: a #GtkTargetList
258 * @target: the interned atom representing the target
259 * @flags: the flags for this target
260 * @info: an ID that will be passed back to the application
262 * Appends another target to a #GtkTargetList.
265 gtk_target_list_add (GtkTargetList *list,
272 g_return_if_fail (list != NULL);
274 pair = g_new (GtkTargetPair, 1);
275 pair->target = target;
279 list->list = g_list_append (list->list, pair);
282 static GdkAtom utf8_atom;
283 static GdkAtom text_atom;
284 static GdkAtom ctext_atom;
285 static GdkAtom text_plain_atom;
286 static GdkAtom text_plain_utf8_atom;
287 static GdkAtom text_plain_locale_atom;
288 static GdkAtom text_uri_list_atom;
294 const gchar *charset;
298 utf8_atom = gdk_atom_intern_static_string ("UTF8_STRING");
299 text_atom = gdk_atom_intern_static_string ("TEXT");
300 ctext_atom = gdk_atom_intern_static_string ("COMPOUND_TEXT");
301 text_plain_atom = gdk_atom_intern_static_string ("text/plain");
302 text_plain_utf8_atom = gdk_atom_intern_static_string ("text/plain;charset=utf-8");
303 g_get_charset (&charset);
304 tmp = g_strdup_printf ("text/plain;charset=%s", charset);
305 text_plain_locale_atom = gdk_atom_intern (tmp, FALSE);
308 text_uri_list_atom = gdk_atom_intern_static_string ("text/uri-list");
313 * gtk_target_list_add_text_targets:
314 * @list: a #GtkTargetList
315 * @info: an ID that will be passed back to the application
317 * Appends the text targets supported by #GtkSelection to
318 * the target list. All targets are added with the same @info.
323 gtk_target_list_add_text_targets (GtkTargetList *list,
326 g_return_if_fail (list != NULL);
330 /* Keep in sync with gtk_selection_data_targets_include_text()
332 gtk_target_list_add (list, utf8_atom, 0, info);
333 gtk_target_list_add (list, ctext_atom, 0, info);
334 gtk_target_list_add (list, text_atom, 0, info);
335 gtk_target_list_add (list, GDK_TARGET_STRING, 0, info);
336 gtk_target_list_add (list, text_plain_utf8_atom, 0, info);
337 gtk_target_list_add (list, text_plain_locale_atom, 0, info);
338 gtk_target_list_add (list, text_plain_atom, 0, info);
342 * gtk_target_list_add_image_targets:
343 * @list: a #GtkTargetList
344 * @info: an ID that will be passed back to the application
345 * @writable: whether to add only targets for which GTK+ knows
346 * how to convert a pixbuf into the format
348 * Appends the image targets supported by #GtkSelection to
349 * the target list. All targets are added with the same @info.
354 gtk_target_list_add_image_targets (GtkTargetList *list,
362 g_return_if_fail (list != NULL);
364 formats = gdk_pixbuf_get_formats ();
366 /* Make sure png comes first */
367 for (f = formats; f; f = f->next)
369 GdkPixbufFormat *fmt = f->data;
372 name = gdk_pixbuf_format_get_name (fmt);
373 if (strcmp (name, "png") == 0)
375 formats = g_slist_delete_link (formats, f);
376 formats = g_slist_prepend (formats, fmt);
386 for (f = formats; f; f = f->next)
388 GdkPixbufFormat *fmt = f->data;
390 if (writable && !gdk_pixbuf_format_is_writable (fmt))
393 mimes = gdk_pixbuf_format_get_mime_types (fmt);
394 for (m = mimes; *m; m++)
396 atom = gdk_atom_intern (*m, FALSE);
397 gtk_target_list_add (list, atom, 0, info);
402 g_slist_free (formats);
406 * gtk_target_list_add_uri_targets:
407 * @list: a #GtkTargetList
408 * @info: an ID that will be passed back to the application
410 * Appends the URI targets supported by #GtkSelection to
411 * the target list. All targets are added with the same @info.
416 gtk_target_list_add_uri_targets (GtkTargetList *list,
419 g_return_if_fail (list != NULL);
423 gtk_target_list_add (list, text_uri_list_atom, 0, info);
427 * gtk_target_list_add_table:
428 * @list: a #GtkTargetList
429 * @targets: the table of #GtkTargetEntry
430 * @ntargets: number of targets in the table
432 * Prepends a table of #GtkTargetEntry to a target list.
435 gtk_target_list_add_table (GtkTargetList *list,
436 const GtkTargetEntry *targets,
441 for (i=ntargets-1; i >= 0; i--)
443 GtkTargetPair *pair = g_new (GtkTargetPair, 1);
444 pair->target = gdk_atom_intern (targets[i].target, FALSE);
445 pair->flags = targets[i].flags;
446 pair->info = targets[i].info;
448 list->list = g_list_prepend (list->list, pair);
453 * gtk_target_list_remove:
454 * @list: a #GtkTargetList
455 * @target: the interned atom representing the target
457 * Removes a target from a target list.
460 gtk_target_list_remove (GtkTargetList *list,
465 g_return_if_fail (list != NULL);
467 tmp_list = list->list;
470 GtkTargetPair *pair = tmp_list->data;
472 if (pair->target == target)
476 list->list = g_list_remove_link (list->list, tmp_list);
477 g_list_free_1 (tmp_list);
482 tmp_list = tmp_list->next;
487 * gtk_target_list_find:
488 * @list: a #GtkTargetList
489 * @target: an interned atom representing the target to search for
490 * @info: a pointer to the location to store application info for target
492 * Looks up a given target in a #GtkTargetList.
494 * Return value: %TRUE if the target was found, otherwise %FALSE
497 gtk_target_list_find (GtkTargetList *list,
501 GList *tmp_list = list->list;
504 GtkTargetPair *pair = tmp_list->data;
506 if (pair->target == target)
511 tmp_list = tmp_list->next;
518 * gtk_selection_owner_set_for_display:
519 * @display: the #Gdkdisplay where the selection is set
520 * @widget: new selection owner (a #GdkWidget), or %NULL.
521 * @selection: an interned atom representing the selection to claim.
522 * @time_: timestamp with which to claim the selection
524 * Claim ownership of a given selection for a particular widget, or,
525 * if @widget is %NULL, release ownership of the selection.
527 * Return value: TRUE if the operation succeeded
532 gtk_selection_owner_set_for_display (GdkDisplay *display,
538 GtkWidget *old_owner;
539 GtkSelectionInfo *selection_info = NULL;
542 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
543 g_return_val_if_fail (selection != GDK_NONE, FALSE);
544 g_return_val_if_fail (widget == NULL || GTK_WIDGET_REALIZED (widget), FALSE);
545 g_return_val_if_fail (widget == NULL || gtk_widget_get_display (widget) == display, FALSE);
550 window = widget->window;
552 tmp_list = current_selections;
555 if (((GtkSelectionInfo *)tmp_list->data)->selection == selection)
557 selection_info = tmp_list->data;
561 tmp_list = tmp_list->next;
564 if (gdk_selection_owner_set_for_display (display, window, selection, time, TRUE))
572 old_owner = selection_info->widget;
573 current_selections = g_list_remove_link (current_selections,
575 g_list_free (tmp_list);
576 g_free (selection_info);
581 if (selection_info == NULL)
583 selection_info = g_new (GtkSelectionInfo, 1);
584 selection_info->selection = selection;
585 selection_info->widget = widget;
586 selection_info->time = time;
587 selection_info->display = display;
588 current_selections = g_list_prepend (current_selections,
593 old_owner = selection_info->widget;
594 selection_info->widget = widget;
595 selection_info->time = time;
596 selection_info->display = display;
599 /* If another widget in the application lost the selection,
600 * send it a GDK_SELECTION_CLEAR event.
602 if (old_owner && old_owner != widget)
604 GdkEvent *event = gdk_event_new (GDK_SELECTION_CLEAR);
606 event->selection.window = g_object_ref (old_owner->window);
607 event->selection.selection = selection;
608 event->selection.time = time;
610 gtk_widget_event (old_owner, event);
612 gdk_event_free (event);
621 * gtk_selection_owner_set:
622 * @widget: a #GtkWidget, or %NULL.
623 * @selection: an interned atom representing the selection to claim
624 * @time_: timestamp with which to claim the selection
626 * Claims ownership of a given selection for a particular widget,
627 * or, if @widget is %NULL, release ownership of the selection.
629 * Return value: %TRUE if the operation succeeded
632 gtk_selection_owner_set (GtkWidget *widget,
638 g_return_val_if_fail (widget == NULL || GTK_WIDGET_REALIZED (widget), FALSE);
639 g_return_val_if_fail (selection != GDK_NONE, FALSE);
642 display = gtk_widget_get_display (widget);
646 g_warning ("gtk_selection_owner_set (NULL,...) is not multihead safe"));
648 display = gdk_display_get_default ();
651 return gtk_selection_owner_set_for_display (display, widget,
655 typedef struct _GtkSelectionTargetList GtkSelectionTargetList;
657 struct _GtkSelectionTargetList {
662 static GtkTargetList *
663 gtk_selection_target_list_get (GtkWidget *widget,
666 GtkSelectionTargetList *sellist;
670 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
675 sellist = tmp_list->data;
676 if (sellist->selection == selection)
677 return sellist->list;
678 tmp_list = tmp_list->next;
681 sellist = g_new (GtkSelectionTargetList, 1);
682 sellist->selection = selection;
683 sellist->list = gtk_target_list_new (NULL, 0);
685 lists = g_list_prepend (lists, sellist);
686 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
688 return sellist->list;
692 gtk_selection_target_list_remove (GtkWidget *widget)
694 GtkSelectionTargetList *sellist;
698 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
703 sellist = tmp_list->data;
705 gtk_target_list_unref (sellist->list);
708 tmp_list = tmp_list->next;
712 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), NULL);
716 * gtk_selection_clear_targets:
717 * @widget: a #GtkWidget
718 * @selection: an atom representing a selection
720 * Remove all targets registered for the given selection for the
724 gtk_selection_clear_targets (GtkWidget *widget,
727 GtkSelectionTargetList *sellist;
731 g_return_if_fail (GTK_IS_WIDGET (widget));
732 g_return_if_fail (selection != GDK_NONE);
734 lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
739 sellist = tmp_list->data;
740 if (sellist->selection == selection)
742 lists = g_list_delete_link (lists, tmp_list);
743 gtk_target_list_unref (sellist->list);
749 tmp_list = tmp_list->next;
752 g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
756 * gtk_selection_add_target:
757 * @widget: a #GtkTarget
758 * @selection: the selection
759 * @target: target to add.
760 * @info: A unsigned integer which will be passed back to the application.
762 * Appends a specified target to the list of supported targets for a
763 * given widget and selection.
766 gtk_selection_add_target (GtkWidget *widget,
773 g_return_if_fail (GTK_IS_WIDGET (widget));
774 g_return_if_fail (selection != GDK_NONE);
776 list = gtk_selection_target_list_get (widget, selection);
777 gtk_target_list_add (list, target, 0, info);
778 #ifdef GDK_WINDOWING_WIN32
779 gdk_win32_selection_add_targets (widget->window, selection, 1, &target);
784 * gtk_selection_add_targets:
785 * @widget: a #GtkWidget
786 * @selection: the selection
787 * @targets: a table of targets to add
788 * @ntargets: number of entries in @targets
790 * Prepends a table of targets to the list of supported targets
791 * for a given widget and selection.
794 gtk_selection_add_targets (GtkWidget *widget,
796 const GtkTargetEntry *targets,
801 g_return_if_fail (GTK_IS_WIDGET (widget));
802 g_return_if_fail (selection != GDK_NONE);
803 g_return_if_fail (targets != NULL);
805 list = gtk_selection_target_list_get (widget, selection);
806 gtk_target_list_add_table (list, targets, ntargets);
808 #ifdef GDK_WINDOWING_WIN32
811 GdkAtom *atoms = g_new (GdkAtom, ntargets);
813 for (i = 0; i < ntargets; ++i)
814 atoms[i] = gdk_atom_intern (targets[i].target, FALSE);
815 gdk_win32_selection_add_targets (widget->window, selection, ntargets, atoms);
823 * gtk_selection_remove_all:
824 * @widget: a #GtkWidget
826 * Removes all handlers and unsets ownership of all
827 * selections for a widget. Called when widget is being
828 * destroyed. This function will not generally be
829 * called by applications.
832 gtk_selection_remove_all (GtkWidget *widget)
836 GtkSelectionInfo *selection_info;
838 /* Remove pending requests/incrs for this widget */
840 tmp_list = current_retrievals;
843 next = tmp_list->next;
844 if (((GtkRetrievalInfo *)tmp_list->data)->widget == widget)
846 current_retrievals = g_list_remove_link (current_retrievals,
848 /* structure will be freed in timeout */
849 g_list_free (tmp_list);
854 /* Disclaim ownership of any selections */
856 tmp_list = current_selections;
859 next = tmp_list->next;
860 selection_info = (GtkSelectionInfo *)tmp_list->data;
862 if (selection_info->widget == widget)
864 gdk_selection_owner_set_for_display (selection_info->display,
866 selection_info->selection,
867 GDK_CURRENT_TIME, FALSE);
868 current_selections = g_list_remove_link (current_selections,
870 g_list_free (tmp_list);
871 g_free (selection_info);
877 /* Remove all selection lists */
878 gtk_selection_target_list_remove (widget);
883 * gtk_selection_convert:
884 * @widget: The widget which acts as requestor
885 * @selection: Which selection to get
886 * @target: Form of information desired (e.g., STRING)
887 * @time_: Time of request (usually of triggering event)
888 In emergency, you could use #GDK_CURRENT_TIME
890 * Requests the contents of a selection. When received,
891 * a "selection_received" signal will be generated.
893 * Return value: %TRUE if requested succeeded. %FALSE if we could not process
894 * request. (e.g., there was already a request in process for
898 gtk_selection_convert (GtkWidget *widget,
903 GtkRetrievalInfo *info;
905 GdkWindow *owner_window;
908 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
909 g_return_val_if_fail (selection != GDK_NONE, FALSE);
912 gtk_selection_init ();
914 if (!GTK_WIDGET_REALIZED (widget))
915 gtk_widget_realize (widget);
917 /* Check to see if there are already any retrievals in progress for
918 this widget. If we changed GDK to use the selection for the
919 window property in which to store the retrieved information, then
920 we could support multiple retrievals for different selections.
921 This might be useful for DND. */
923 tmp_list = current_retrievals;
926 info = (GtkRetrievalInfo *)tmp_list->data;
927 if (info->widget == widget)
929 tmp_list = tmp_list->next;
932 info = g_new (GtkRetrievalInfo, 1);
934 info->widget = widget;
935 info->selection = selection;
936 info->target = target;
941 /* Check if this process has current owner. If so, call handler
942 procedure directly to avoid deadlocks with INCR. */
944 display = gtk_widget_get_display (widget);
945 owner_window = gdk_selection_owner_get_for_display (display, selection);
947 if (owner_window != NULL)
949 GtkWidget *owner_widget;
950 GtkSelectionData selection_data;
952 selection_data.selection = selection;
953 selection_data.target = target;
954 selection_data.data = NULL;
955 selection_data.length = -1;
956 selection_data.display = display;
958 gdk_window_get_user_data (owner_window, (gpointer *)&owner_widget);
960 if (owner_widget != NULL)
962 gtk_selection_invoke_handler (owner_widget,
966 gtk_selection_retrieval_report (info,
968 selection_data.format,
970 selection_data.length,
973 g_free (selection_data.data);
980 /* Otherwise, we need to go through X */
982 current_retrievals = g_list_append (current_retrievals, info);
983 gdk_selection_convert (widget->window, selection, target, time_);
984 g_timeout_add (1000, (GSourceFunc) gtk_selection_retrieval_timeout, info);
991 * gtk_selection_data_set:
992 * @selection_data: a pointer to a #GtkSelectionData structure.
993 * @type: the type of selection data
994 * @format: format (number of bits in a unit)
995 * @data: pointer to the data (will be copied)
996 * @length: length of the data
998 * Stores new data into a #GtkSelectionData object. Should
999 * <emphasis>only</emphasis> be called from a selection handler callback.
1000 * Zero-terminates the stored data.
1003 gtk_selection_data_set (GtkSelectionData *selection_data,
1009 if (selection_data->data)
1010 g_free (selection_data->data);
1012 selection_data->type = type;
1013 selection_data->format = format;
1017 selection_data->data = g_new (guchar, length+1);
1018 memcpy (selection_data->data, data, length);
1019 selection_data->data[length] = 0;
1023 g_return_if_fail (length <= 0);
1026 selection_data->data = NULL;
1028 selection_data->data = g_strdup("");
1031 selection_data->length = length;
1035 selection_set_string (GtkSelectionData *selection_data,
1039 gchar *tmp = g_strndup (str, len);
1040 gchar *latin1 = gdk_utf8_to_string_target (tmp);
1045 gtk_selection_data_set (selection_data,
1046 GDK_SELECTION_TYPE_STRING,
1047 8, latin1, strlen (latin1));
1057 selection_set_compound_text (GtkSelectionData *selection_data,
1066 gboolean result = FALSE;
1068 tmp = g_strndup (str, len);
1069 if (gdk_utf8_to_compound_text_for_display (selection_data->display, tmp,
1070 &encoding, &format, &text, &new_length))
1072 gtk_selection_data_set (selection_data, encoding, format, text, new_length);
1073 gdk_free_compound_text (text);
1083 /* Normalize \r and \n into \r\n
1086 normalize_to_crlf (const gchar *str,
1089 GString *result = g_string_sized_new (len);
1090 const gchar *p = str;
1095 g_string_append_c (result, '\r');
1099 g_string_append_c (result, *p);
1102 g_string_append_c (result, '\n');
1108 g_string_append_c (result, *p);
1112 return g_string_free (result, FALSE);
1115 /* Normalize \r and \r\n into \n
1118 normalize_to_lf (gchar *str,
1121 GString *result = g_string_sized_new (len);
1122 const gchar *p = str;
1130 g_string_append_c (result, '\n');
1136 g_string_append_c (result, *p);
1140 return g_string_free (result, FALSE);
1144 selection_set_text_plain (GtkSelectionData *selection_data,
1148 const gchar *charset = NULL;
1150 GError *error = NULL;
1152 result = normalize_to_crlf (str, len);
1153 if (selection_data->target == text_plain_atom)
1155 else if (selection_data->target == text_plain_locale_atom)
1156 g_get_charset (&charset);
1160 gchar *tmp = result;
1161 result = g_convert_with_fallback (tmp, -1,
1163 NULL, NULL, NULL, &error);
1169 g_warning ("Error converting from UTF-8 to %s: %s",
1170 charset, error->message);
1171 g_error_free (error);
1176 gtk_selection_data_set (selection_data,
1177 selection_data->target,
1178 8, result, strlen (result));
1185 selection_get_text_plain (GtkSelectionData *selection_data)
1187 const gchar *charset = NULL;
1188 gchar *str, *result;
1190 GError *error = NULL;
1192 str = g_strdup (selection_data->data);
1193 len = selection_data->length;
1195 if (selection_data->type == text_plain_atom)
1196 charset = "ISO-8859-1";
1197 else if (selection_data->type == text_plain_locale_atom)
1198 g_get_charset (&charset);
1203 str = g_convert_with_fallback (tmp, len,
1205 NULL, NULL, &len, &error);
1210 g_warning ("Error converting from %s to UTF-8: %s",
1211 charset, error->message);
1212 g_error_free (error);
1217 else if (!g_utf8_validate (str, -1, NULL))
1219 g_warning ("Error converting from text/plain;charset=utf-8 to UTF-8");
1225 result = normalize_to_lf (str, len);
1232 * gtk_selection_data_set_text:
1233 * @selection_data: a #GtkSelectionData
1234 * @str: a UTF-8 string
1235 * @len: the length of @str, or -1 if @str is nul-terminated.
1237 * Sets the contents of the selection from a UTF-8 encoded string.
1238 * The string is converted to the form determined by
1239 * @selection_data->target.
1241 * Return value: %TRUE if the selection was successfully set,
1245 gtk_selection_data_set_text (GtkSelectionData *selection_data,
1254 if (selection_data->target == utf8_atom)
1256 gtk_selection_data_set (selection_data,
1258 8, (guchar *)str, len);
1261 else if (selection_data->target == GDK_TARGET_STRING)
1263 return selection_set_string (selection_data, str, len);
1265 else if (selection_data->target == ctext_atom ||
1266 selection_data->target == text_atom)
1268 if (selection_set_compound_text (selection_data, str, len))
1270 else if (selection_data->target == text_atom)
1271 return selection_set_string (selection_data, str, len);
1273 else if (selection_data->target == text_plain_atom ||
1274 selection_data->target == text_plain_utf8_atom ||
1275 selection_data->target == text_plain_locale_atom)
1277 return selection_set_text_plain (selection_data, str, len);
1284 * gtk_selection_data_get_text:
1285 * @selection_data: a #GtkSelectionData
1287 * Gets the contents of the selection data as a UTF-8 string.
1289 * Return value: if the selection data contained a recognized
1290 * text type and it could be converted to UTF-8, a newly allocated
1291 * string containing the converted text, otherwise %NULL.
1292 * If the result is non-%NULL it must be freed with g_free().
1295 gtk_selection_data_get_text (GtkSelectionData *selection_data)
1297 guchar *result = NULL;
1301 if (selection_data->length >= 0 &&
1302 (selection_data->type == GDK_TARGET_STRING ||
1303 selection_data->type == ctext_atom ||
1304 selection_data->type == utf8_atom))
1308 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1309 selection_data->type,
1310 selection_data->format,
1311 selection_data->data,
1312 selection_data->length,
1317 for (i = 1; i < count; i++)
1321 else if (selection_data->length >= 0 &&
1322 (selection_data->type == text_plain_atom ||
1323 selection_data->type == text_plain_utf8_atom ||
1324 selection_data->type == text_plain_locale_atom))
1326 result = selection_get_text_plain (selection_data);
1333 * gtk_selection_data_set_pixbuf:
1334 * @selection_data: a #GtkSelectionData
1335 * @pixbuf: a #GdkPixbuf
1337 * Sets the contents of the selection from a #GdkPixbuf
1338 * The pixbuf is converted to the form determined by
1339 * @selection_data->target.
1341 * Return value: %TRUE if the selection was successfully set,
1347 gtk_selection_data_set_pixbuf (GtkSelectionData *selection_data,
1350 GSList *formats, *f;
1357 formats = gdk_pixbuf_get_formats ();
1359 for (f = formats; f; f = f->next)
1361 GdkPixbufFormat *fmt = f->data;
1363 mimes = gdk_pixbuf_format_get_mime_types (fmt);
1364 for (m = mimes; *m; m++)
1366 atom = gdk_atom_intern (*m, FALSE);
1367 if (selection_data->target == atom)
1370 type = gdk_pixbuf_format_get_name (fmt);
1371 result = gdk_pixbuf_save_to_buffer (pixbuf, &str, &len,
1373 ((strcmp (type, "png") == 0) ?
1374 "compression" : NULL), "2",
1377 gtk_selection_data_set (selection_data,
1378 atom, 8, (guchar *)str, len);
1382 g_slist_free (formats);
1391 g_slist_free (formats);
1397 * gtk_selection_data_get_pixbuf:
1398 * @selection_data: a #GtkSelectionData
1400 * Gets the contents of the selection data as a #GdkPixbuf.
1402 * Return value: if the selection data contained a recognized
1403 * image type and it could be converted to a #GdkPixbuf, a
1404 * newly allocated pixbuf is returned, otherwise %NULL.
1405 * If the result is non-%NULL it must be freed with g_object_unref().
1410 gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data)
1412 GdkPixbufLoader *loader;
1413 GdkPixbuf *result = NULL;
1415 if (selection_data->length > 0)
1417 loader = gdk_pixbuf_loader_new ();
1419 gdk_pixbuf_loader_write (loader,
1420 selection_data->data,
1421 selection_data->length,
1423 gdk_pixbuf_loader_close (loader, NULL);
1424 result = gdk_pixbuf_loader_get_pixbuf (loader);
1427 g_object_ref (result);
1429 g_object_unref (loader);
1436 * gtk_selection_data_set_uris:
1437 * @selection_data: a #GtkSelectionData
1438 * @uris: a %NULL-terminated array of strings hilding URIs
1440 * Sets the contents of the selection from a list of URIs.
1441 * The string is converted to the form determined by
1442 * @selection_data->target.
1444 * Return value: %TRUE if the selection was successfully set,
1450 gtk_selection_data_set_uris (GtkSelectionData *selection_data,
1455 if (selection_data->target == text_uri_list_atom)
1462 list = g_string_new (NULL);
1463 for (i = 0; uris[i]; i++)
1465 g_string_append (list, uris[i]);
1466 g_string_append (list, "\r\n");
1469 result = g_convert (list->str, list->len,
1471 NULL, &length, NULL);
1472 g_string_free (list, TRUE);
1476 gtk_selection_data_set (selection_data,
1478 8, (guchar *)result, length);
1490 * gtk_selection_data_get_uris:
1491 * @selection_data: a #GtkSelectionData
1493 * Gets the contents of the selection data as array of URIs.
1495 * Return value: if the selection data contains a list of
1496 * URIs, a newly allocated %NULL-terminated string array
1497 * containing the URIs, otherwise %NULL. If the result is
1498 * non-%NULL it must be freed with g_strfreev().
1503 gtk_selection_data_get_uris (GtkSelectionData *selection_data)
1505 gchar **result = NULL;
1509 if (selection_data->length >= 0 &&
1510 selection_data->type == text_uri_list_atom)
1514 gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display,
1516 selection_data->format,
1517 selection_data->data,
1518 selection_data->length,
1521 result = g_uri_list_extract_uris (list[0]);
1531 * gtk_selection_data_get_targets:
1532 * @selection_data: a #GtkSelectionData object
1533 * @targets: location to store an array of targets. The result
1534 * stored here must be freed with g_free().
1535 * @n_atoms: location to store number of items in @targets.
1537 * Gets the contents of @selection_data as an array of targets.
1538 * This can be used to interpret the results of getting
1539 * the standard TARGETS target that is always supplied for
1542 * Return value: %TRUE if @selection_data contains a valid
1543 * array of targets, otherwise %FALSE.
1546 gtk_selection_data_get_targets (GtkSelectionData *selection_data,
1550 if (selection_data->length >= 0 &&
1551 selection_data->format == 32 &&
1552 selection_data->type == GDK_SELECTION_TYPE_ATOM)
1555 *targets = g_memdup (selection_data->data, selection_data->length);
1557 *n_atoms = selection_data->length / sizeof (GdkAtom);
1573 * gtk_targets_include_text:
1574 * @targets: an array of #GdkAtom<!-- -->s
1575 * @n_targets: the length of @targets
1577 * Determines if any of the targets in @targets can be used to
1580 * Return value: %TRUE if @targets include a suitable target for text,
1586 gtk_targets_include_text (GdkAtom *targets,
1590 gboolean result = FALSE;
1592 /* Keep in sync with gtk_target_list_add_text_targets()
1594 for (i = 0; i < n_targets; i++)
1596 if (targets[i] == utf8_atom ||
1597 targets[i] == text_atom ||
1598 targets[i] == GDK_TARGET_STRING ||
1599 targets[i] == ctext_atom ||
1600 targets[i] == text_plain_atom ||
1601 targets[i] == text_plain_utf8_atom ||
1602 targets[i] == text_plain_locale_atom)
1613 * gtk_selection_data_targets_include_text:
1614 * @selection_data: a #GtkSelectionData object
1616 * Given a #GtkSelectionData object holding a list of targets,
1617 * determines if any of the targets in @targets can be used to
1620 * Return value: %TRUE if @selection_data holds a list of targets,
1621 * and a suitable target for text is included, otherwise %FALSE.
1624 gtk_selection_data_targets_include_text (GtkSelectionData *selection_data)
1628 gboolean result = FALSE;
1632 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1634 result = gtk_targets_include_text (targets, n_targets);
1642 * gtk_targets_include_image:
1643 * @targets: an array of #GdkAtom<!-- -->s
1644 * @n_targets: the length of @targets
1645 * @writable: whether to accept only targets for which GTK+ knows
1646 * how to convert a pixbuf into the format
1648 * Determines if any of the targets in @targets can be used to
1649 * provide a #GdkPixbuf.
1651 * Return value: %TRUE if @targets include a suitable target for images,
1657 gtk_targets_include_image (GdkAtom *targets,
1661 GtkTargetList *list;
1664 gboolean result = FALSE;
1666 list = gtk_target_list_new (NULL, 0);
1667 gtk_target_list_add_image_targets (list, 0, writable);
1668 for (i = 0; i < n_targets && !result; i++)
1670 for (l = list->list; l; l = l->next)
1672 GtkTargetPair *pair = (GtkTargetPair *)l->data;
1673 if (pair->target == targets[i])
1680 gtk_target_list_unref (list);
1686 * gtk_selection_data_targets_include_image:
1687 * @selection_data: a #GtkSelectionData object
1688 * @writable: whether to accept only targets for which GTK+ knows
1689 * how to convert a pixbuf into the format
1691 * Given a #GtkSelectionData object holding a list of targets,
1692 * determines if any of the targets in @targets can be used to
1693 * provide a #GdkPixbuf.
1695 * Return value: %TRUE if @selection_data holds a list of targets,
1696 * and a suitable target for images is included, otherwise %FALSE.
1701 gtk_selection_data_targets_include_image (GtkSelectionData *selection_data,
1706 gboolean result = FALSE;
1710 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1712 result = gtk_targets_include_image (targets, n_targets, writable);
1720 * gtk_targets_include_uri:
1721 * @targets: an array of #GdkAtom<!-- -->s
1722 * @n_targets: the length of @targets
1724 * Determines if any of the targets in @targets can be used to
1725 * provide an uri list.
1727 * Return value: %TRUE if @targets include a suitable target for uri lists,
1733 gtk_targets_include_uri (GdkAtom *targets,
1737 gboolean result = FALSE;
1739 /* Keep in sync with gtk_target_list_add_uri_targets()
1741 for (i = 0; i < n_targets; i++)
1743 if (targets[i] == text_uri_list_atom)
1754 * gtk_selection_data_targets_include_uri:
1755 * @selection_data: a #GtkSelectionData object
1757 * Given a #GtkSelectionData object holding a list of targets,
1758 * determines if any of the targets in @targets can be used to
1759 * provide a list or URIs.
1761 * Return value: %TRUE if @selection_data holds a list of targets,
1762 * and a suitable target for text is included, otherwise %FALSE.
1767 gtk_selection_data_targets_include_uri (GtkSelectionData *selection_data)
1771 gboolean result = FALSE;
1775 if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
1777 result = gtk_targets_include_uri (targets, n_targets);
1785 /*************************************************************
1786 * gtk_selection_init:
1787 * Initialize local variables
1791 *************************************************************/
1794 gtk_selection_init (void)
1796 gtk_selection_atoms[INCR] = gdk_atom_intern_static_string ("INCR");
1797 gtk_selection_atoms[MULTIPLE] = gdk_atom_intern_static_string ("MULTIPLE");
1798 gtk_selection_atoms[TIMESTAMP] = gdk_atom_intern_static_string ("TIMESTAMP");
1799 gtk_selection_atoms[TARGETS] = gdk_atom_intern_static_string ("TARGETS");
1805 * gtk_selection_clear:
1806 * @widget: a #GtkWidget
1809 * The default handler for the GtkWidget::selection_clear_event
1812 * Return value: %TRUE if the event was handled, otherwise false
1816 * Deprecated: 2.4: Instead of calling this function, chain up from
1817 * your selection_clear_event handler. Calling this function
1818 * from any other context is illegal.
1821 gtk_selection_clear (GtkWidget *widget,
1822 GdkEventSelection *event)
1824 /* Note that we filter clear events in gdkselection-x11.c, so
1825 * that we only will get here if the clear event actually
1826 * represents a change that we didn't do ourself.
1829 GtkSelectionInfo *selection_info = NULL;
1831 tmp_list = current_selections;
1834 selection_info = (GtkSelectionInfo *)tmp_list->data;
1836 if ((selection_info->selection == event->selection) &&
1837 (selection_info->widget == widget))
1840 tmp_list = tmp_list->next;
1845 current_selections = g_list_remove_link (current_selections, tmp_list);
1846 g_list_free (tmp_list);
1847 g_free (selection_info);
1854 /*************************************************************
1855 * _gtk_selection_request:
1856 * Handler for "selection_request_event"
1861 *************************************************************/
1864 _gtk_selection_request (GtkWidget *widget,
1865 GdkEventSelection *event)
1867 GdkDisplay *display = gtk_widget_get_display (widget);
1871 gulong selection_max_size;
1874 gtk_selection_init ();
1876 selection_max_size = GTK_SELECTION_MAX_SIZE (display);
1878 /* Check if we own selection */
1880 tmp_list = current_selections;
1883 GtkSelectionInfo *selection_info = (GtkSelectionInfo *)tmp_list->data;
1885 if ((selection_info->selection == event->selection) &&
1886 (selection_info->widget == widget))
1889 tmp_list = tmp_list->next;
1892 if (tmp_list == NULL)
1895 info = g_new (GtkIncrInfo, 1);
1897 g_object_ref (widget);
1899 info->selection = event->selection;
1900 info->num_incrs = 0;
1902 /* Create GdkWindow structure for the requestor */
1904 info->requestor = gdk_window_lookup_for_display (display,
1906 if (!info->requestor)
1907 info->requestor = gdk_window_foreign_new_for_display (display,
1910 /* Determine conversions we need to perform */
1912 if (event->target == gtk_selection_atoms[MULTIPLE])
1921 gdk_error_trap_push ();
1922 if (!gdk_property_get (info->requestor, event->property, GDK_NONE, /* AnyPropertyType */
1923 0, selection_max_size, FALSE,
1924 &type, &format, &length, &mult_atoms))
1926 gdk_selection_send_notify_for_display (display,
1932 g_free (mult_atoms);
1936 gdk_error_trap_pop ();
1938 /* This is annoying; the ICCCM doesn't specify the property type
1939 * used for the property contents, so the autoconversion for
1940 * ATOM / ATOM_PAIR in GDK doesn't work properly.
1942 #ifdef GDK_WINDOWING_X11
1943 if (type != GDK_SELECTION_TYPE_ATOM &&
1944 type != gdk_atom_intern_static_string ("ATOM_PAIR"))
1946 info->num_conversions = length / (2*sizeof (glong));
1947 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
1949 for (i=0; i<info->num_conversions; i++)
1951 info->conversions[i].target = gdk_x11_xatom_to_atom_for_display (display,
1952 ((glong *)mult_atoms)[2*i]);
1953 info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display,
1954 ((glong *)mult_atoms)[2*i + 1]);
1957 g_free (mult_atoms);
1962 info->num_conversions = length / (2*sizeof (GdkAtom));
1963 info->conversions = g_new (GtkIncrConversion, info->num_conversions);
1965 for (i=0; i<info->num_conversions; i++)
1967 info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i];
1968 info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1];
1972 else /* only a single conversion */
1974 info->conversions = g_new (GtkIncrConversion, 1);
1975 info->num_conversions = 1;
1976 info->conversions[0].target = event->target;
1977 info->conversions[0].property = event->property;
1980 /* Loop through conversions and determine which of these are big
1981 enough to require doing them via INCR */
1982 for (i=0; i<info->num_conversions; i++)
1984 GtkSelectionData data;
1987 data.selection = event->selection;
1988 data.target = info->conversions[i].target;
1991 data.display = gtk_widget_get_display (widget);
1993 #ifdef DEBUG_SELECTION
1994 g_message ("Selection %ld, target %ld (%s) requested by 0x%x (property = %ld)",
1996 info->conversions[i].target,
1997 gdk_atom_name (info->conversions[i].target),
1998 event->requestor, info->conversions[i].property);
2001 gtk_selection_invoke_handler (widget, &data, event->time);
2003 if (data.length < 0)
2005 info->conversions[i].property = GDK_NONE;
2009 g_return_val_if_fail ((data.format >= 8) && (data.format % 8 == 0), FALSE);
2011 items = data.length / gtk_selection_bytes_per_item (data.format);
2013 if (data.length > selection_max_size)
2015 /* Sending via INCR */
2016 #ifdef DEBUG_SELECTION
2017 g_message ("Target larger (%d) than max. request size (%ld), sending incrementally\n",
2018 data.length, selection_max_size);
2021 info->conversions[i].offset = 0;
2022 info->conversions[i].data = data;
2025 gdk_property_change (info->requestor,
2026 info->conversions[i].property,
2027 gtk_selection_atoms[INCR],
2029 GDK_PROP_MODE_REPLACE,
2030 (guchar *)&items, 1);
2034 info->conversions[i].offset = -1;
2036 gdk_property_change (info->requestor,
2037 info->conversions[i].property,
2040 GDK_PROP_MODE_REPLACE,
2047 /* If we have some INCR's, we need to send the rest of the data in
2050 if (info->num_incrs > 0)
2052 /* FIXME: this could be dangerous if window doesn't still
2055 #ifdef DEBUG_SELECTION
2056 g_message ("Starting INCR...");
2059 gdk_window_set_events (info->requestor,
2060 gdk_window_get_events (info->requestor) |
2061 GDK_PROPERTY_CHANGE_MASK);
2062 current_incrs = g_list_append (current_incrs, info);
2063 g_timeout_add (1000, (GSourceFunc) gtk_selection_incr_timeout, info);
2066 /* If it was a MULTIPLE request, set the property to indicate which
2067 conversions succeeded */
2068 if (event->target == gtk_selection_atoms[MULTIPLE])
2070 GdkAtom *mult_atoms = g_new (GdkAtom, 2 * info->num_conversions);
2071 for (i = 0; i < info->num_conversions; i++)
2073 mult_atoms[2*i] = info->conversions[i].target;
2074 mult_atoms[2*i+1] = info->conversions[i].property;
2077 gdk_property_change (info->requestor, event->property,
2078 gdk_atom_intern_static_string ("ATOM_PAIR"), 32,
2079 GDK_PROP_MODE_REPLACE,
2080 (guchar *)mult_atoms, 2*info->num_conversions);
2081 g_free (mult_atoms);
2084 if (info->num_conversions == 1 &&
2085 info->conversions[0].property == GDK_NONE)
2087 /* Reject the entire conversion */
2088 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2097 gdk_selection_send_notify_for_display (gtk_widget_get_display (widget),
2105 if (info->num_incrs == 0)
2107 g_free (info->conversions);
2111 g_object_unref (widget);
2116 /*************************************************************
2117 * _gtk_selection_incr_event:
2118 * Called whenever an PropertyNotify event occurs for an
2119 * GdkWindow with user_data == NULL. These will be notifications
2120 * that a window we are sending the selection to via the
2121 * INCR protocol has deleted a property and is ready for
2125 * window: the requestor window
2126 * event: the property event structure
2129 *************************************************************/
2132 _gtk_selection_incr_event (GdkWindow *window,
2133 GdkEventProperty *event)
2136 GtkIncrInfo *info = NULL;
2139 gulong selection_max_size;
2143 if (event->state != GDK_PROPERTY_DELETE)
2146 #ifdef DEBUG_SELECTION
2147 g_message ("PropertyDelete, property %ld", event->atom);
2150 selection_max_size = GTK_SELECTION_MAX_SIZE (gdk_drawable_get_display (window));
2152 /* Now find the appropriate ongoing INCR */
2153 tmp_list = current_incrs;
2156 info = (GtkIncrInfo *)tmp_list->data;
2157 if (info->requestor == event->window)
2160 tmp_list = tmp_list->next;
2163 if (tmp_list == NULL)
2166 /* Find out which target this is for */
2167 for (i=0; i<info->num_conversions; i++)
2169 if (info->conversions[i].property == event->atom &&
2170 info->conversions[i].offset != -1)
2174 info->idle_time = 0;
2176 if (info->conversions[i].offset == -2) /* only the last 0-length
2184 num_bytes = info->conversions[i].data.length -
2185 info->conversions[i].offset;
2186 buffer = info->conversions[i].data.data +
2187 info->conversions[i].offset;
2189 if (num_bytes > selection_max_size)
2191 num_bytes = selection_max_size;
2192 info->conversions[i].offset += selection_max_size;
2195 info->conversions[i].offset = -2;
2197 #ifdef DEBUG_SELECTION
2198 g_message ("INCR: put %d bytes (offset = %d) into window 0x%lx , property %ld",
2199 num_bytes, info->conversions[i].offset,
2200 GDK_WINDOW_XWINDOW(info->requestor), event->atom);
2203 bytes_per_item = gtk_selection_bytes_per_item (info->conversions[i].data.format);
2204 gdk_property_change (info->requestor, event->atom,
2205 info->conversions[i].data.type,
2206 info->conversions[i].data.format,
2207 GDK_PROP_MODE_REPLACE,
2209 num_bytes / bytes_per_item);
2211 if (info->conversions[i].offset == -2)
2213 g_free (info->conversions[i].data.data);
2214 info->conversions[i].data.data = NULL;
2220 info->conversions[i].offset = -1;
2225 /* Check if we're finished with all the targets */
2227 if (info->num_incrs == 0)
2229 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2230 g_list_free (tmp_list);
2231 /* Let the timeout free it */
2237 /*************************************************************
2238 * gtk_selection_incr_timeout:
2239 * Timeout callback for the sending portion of the INCR
2242 * info: Information about this incr
2244 *************************************************************/
2247 gtk_selection_incr_timeout (GtkIncrInfo *info)
2252 GDK_THREADS_ENTER ();
2254 /* Determine if retrieval has finished by checking if it still in
2255 list of pending retrievals */
2257 tmp_list = current_incrs;
2260 if (info == (GtkIncrInfo *)tmp_list->data)
2262 tmp_list = tmp_list->next;
2265 /* If retrieval is finished */
2266 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2268 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2270 current_incrs = g_list_remove_link (current_incrs, tmp_list);
2271 g_list_free (tmp_list);
2274 g_free (info->conversions);
2275 /* FIXME: we should check if requestor window is still in use,
2276 and if not, remove it? */
2280 retval = FALSE; /* remove timeout */
2286 retval = TRUE; /* timeout will happen again */
2289 GDK_THREADS_LEAVE ();
2294 /*************************************************************
2295 * _gtk_selection_notify:
2296 * Handler for "selection_notify_event" signals on windows
2297 * where a retrieval is currently in process. The selection
2298 * owner has responded to our conversion request.
2300 * widget: Widget getting signal
2301 * event: Selection event structure
2302 * info: Information about this retrieval
2304 * was event handled?
2305 *************************************************************/
2308 _gtk_selection_notify (GtkWidget *widget,
2309 GdkEventSelection *event)
2312 GtkRetrievalInfo *info = NULL;
2313 guchar *buffer = NULL;
2318 #ifdef DEBUG_SELECTION
2319 g_message ("Initial receipt of selection %ld, target %ld (property = %ld)",
2320 event->selection, event->target, event->property);
2323 tmp_list = current_retrievals;
2326 info = (GtkRetrievalInfo *)tmp_list->data;
2327 if (info->widget == widget && info->selection == event->selection)
2329 tmp_list = tmp_list->next;
2332 if (!tmp_list) /* no retrieval in progress */
2335 if (event->property != GDK_NONE)
2336 length = gdk_selection_property_get (widget->window, &buffer,
2339 length = 0; /* silence gcc */
2341 if (event->property == GDK_NONE || buffer == NULL)
2343 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2344 g_list_free (tmp_list);
2345 /* structure will be freed in timeout */
2346 gtk_selection_retrieval_report (info,
2347 GDK_NONE, 0, NULL, -1, event->time);
2352 if (type == gtk_selection_atoms[INCR])
2354 /* The remainder of the selection will come through PropertyNotify
2357 info->notify_time = event->time;
2358 info->idle_time = 0;
2359 info->offset = 0; /* Mark as OK to proceed */
2360 gdk_window_set_events (widget->window,
2361 gdk_window_get_events (widget->window)
2362 | GDK_PROPERTY_CHANGE_MASK);
2366 /* We don't delete the info structure - that will happen in timeout */
2367 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2368 g_list_free (tmp_list);
2370 info->offset = length;
2371 gtk_selection_retrieval_report (info,
2373 buffer, length, event->time);
2376 gdk_property_delete (widget->window, event->property);
2383 /*************************************************************
2384 * _gtk_selection_property_notify:
2385 * Handler for "property_notify_event" signals on windows
2386 * where a retrieval is currently in process. The selection
2387 * owner has added more data.
2389 * widget: Widget getting signal
2390 * event: Property event structure
2391 * info: Information about this retrieval
2393 * was event handled?
2394 *************************************************************/
2397 _gtk_selection_property_notify (GtkWidget *widget,
2398 GdkEventProperty *event)
2401 GtkRetrievalInfo *info = NULL;
2407 g_return_val_if_fail (widget != NULL, FALSE);
2408 g_return_val_if_fail (event != NULL, FALSE);
2410 #if defined(GDK_WINDOWING_WIN32) || defined(GDK_WINDOWING_X11)
2411 if ((event->state != GDK_PROPERTY_NEW_VALUE) || /* property was deleted */
2412 (event->atom != gdk_atom_intern_static_string ("GDK_SELECTION"))) /* not the right property */
2416 #ifdef DEBUG_SELECTION
2417 g_message ("PropertyNewValue, property %ld",
2421 tmp_list = current_retrievals;
2424 info = (GtkRetrievalInfo *)tmp_list->data;
2425 if (info->widget == widget)
2427 tmp_list = tmp_list->next;
2430 if (!tmp_list) /* No retrieval in progress */
2433 if (info->offset < 0) /* We haven't got the SelectionNotify
2434 for this retrieval yet */
2437 info->idle_time = 0;
2439 length = gdk_selection_property_get (widget->window, &new_buffer,
2441 gdk_property_delete (widget->window, event->atom);
2443 /* We could do a lot better efficiency-wise by paying attention to
2444 what length was sent in the initial INCR transaction, instead of
2445 doing memory allocation at every step. But its only guaranteed to
2446 be a _lower bound_ (pretty useless!) */
2448 if (length == 0 || type == GDK_NONE) /* final zero length portion */
2450 /* Info structure will be freed in timeout */
2451 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2452 g_list_free (tmp_list);
2453 gtk_selection_retrieval_report (info,
2455 (type == GDK_NONE) ? NULL : info->buffer,
2456 (type == GDK_NONE) ? -1 : info->offset,
2459 else /* append on newly arrived data */
2463 #ifdef DEBUG_SELECTION
2464 g_message ("Start - Adding %d bytes at offset 0",
2467 info->buffer = new_buffer;
2468 info->offset = length;
2473 #ifdef DEBUG_SELECTION
2474 g_message ("Appending %d bytes at offset %d",
2475 length,info->offset);
2477 /* We copy length+1 bytes to preserve guaranteed null termination */
2478 info->buffer = g_realloc (info->buffer, info->offset+length+1);
2479 memcpy (info->buffer + info->offset, new_buffer, length+1);
2480 info->offset += length;
2481 g_free (new_buffer);
2488 /*************************************************************
2489 * gtk_selection_retrieval_timeout:
2490 * Timeout callback while receiving a selection.
2492 * info: Information about this retrieval
2494 *************************************************************/
2497 gtk_selection_retrieval_timeout (GtkRetrievalInfo *info)
2502 GDK_THREADS_ENTER ();
2504 /* Determine if retrieval has finished by checking if it still in
2505 list of pending retrievals */
2507 tmp_list = current_retrievals;
2510 if (info == (GtkRetrievalInfo *)tmp_list->data)
2512 tmp_list = tmp_list->next;
2515 /* If retrieval is finished */
2516 if (!tmp_list || info->idle_time >= IDLE_ABORT_TIME)
2518 if (tmp_list && info->idle_time >= IDLE_ABORT_TIME)
2520 current_retrievals = g_list_remove_link (current_retrievals, tmp_list);
2521 g_list_free (tmp_list);
2522 gtk_selection_retrieval_report (info, GDK_NONE, 0, NULL, -1, GDK_CURRENT_TIME);
2525 g_free (info->buffer);
2528 retval = FALSE; /* remove timeout */
2534 retval = TRUE; /* timeout will happen again */
2537 GDK_THREADS_LEAVE ();
2542 /*************************************************************
2543 * gtk_selection_retrieval_report:
2544 * Emits a "selection_received" signal.
2546 * info: information about the retrieval that completed
2547 * buffer: buffer containing data (NULL => errror)
2548 * time: timestamp for data in buffer
2550 *************************************************************/
2553 gtk_selection_retrieval_report (GtkRetrievalInfo *info,
2554 GdkAtom type, gint format,
2555 guchar *buffer, gint length,
2558 GtkSelectionData data;
2560 data.selection = info->selection;
2561 data.target = info->target;
2563 data.format = format;
2565 data.length = length;
2567 data.display = gtk_widget_get_display (info->widget);
2569 g_signal_emit_by_name (info->widget,
2570 "selection_received",
2574 /*************************************************************
2575 * gtk_selection_invoke_handler:
2576 * Finds and invokes handler for specified
2577 * widget/selection/target combination, calls
2578 * gtk_selection_default_handler if none exists.
2581 * widget: selection owner
2582 * data: selection data [INOUT]
2583 * time: time from requeset
2586 * Number of bytes written to buffer, -1 if error
2587 *************************************************************/
2590 gtk_selection_invoke_handler (GtkWidget *widget,
2591 GtkSelectionData *data,
2594 GtkTargetList *target_list;
2598 g_return_if_fail (widget != NULL);
2600 target_list = gtk_selection_target_list_get (widget, data->selection);
2602 gtk_target_list_find (target_list, data->target, &info))
2604 g_signal_emit_by_name (widget,
2610 gtk_selection_default_handler (widget, data);
2613 /*************************************************************
2614 * gtk_selection_default_handler:
2615 * Handles some default targets that exist for any widget
2616 * If it can't fit results into buffer, returns -1. This
2617 * won't happen in any conceivable case, since it would
2618 * require 1000 selection targets!
2621 * widget: selection owner
2622 * data: selection data [INOUT]
2624 *************************************************************/
2627 gtk_selection_default_handler (GtkWidget *widget,
2628 GtkSelectionData *data)
2630 if (data->target == gtk_selection_atoms[TIMESTAMP])
2632 /* Time which was used to obtain selection */
2634 GtkSelectionInfo *selection_info;
2636 tmp_list = current_selections;
2639 selection_info = (GtkSelectionInfo *)tmp_list->data;
2640 if ((selection_info->widget == widget) &&
2641 (selection_info->selection == data->selection))
2643 gulong time = selection_info->time;
2645 gtk_selection_data_set (data,
2646 GDK_SELECTION_TYPE_INTEGER,
2653 tmp_list = tmp_list->next;
2658 else if (data->target == gtk_selection_atoms[TARGETS])
2660 /* List of all targets supported for this widget/selection pair */
2664 GtkTargetList *target_list;
2665 GtkTargetPair *pair;
2667 target_list = gtk_selection_target_list_get (widget,
2669 count = g_list_length (target_list->list) + 3;
2671 data->type = GDK_SELECTION_TYPE_ATOM;
2673 data->length = count * sizeof (GdkAtom);
2675 /* selection data is always terminated by a trailing \0
2677 p = g_malloc (data->length + 1);
2678 data->data = (guchar *)p;
2679 data->data[data->length] = '\0';
2681 *p++ = gtk_selection_atoms[TIMESTAMP];
2682 *p++ = gtk_selection_atoms[TARGETS];
2683 *p++ = gtk_selection_atoms[MULTIPLE];
2685 tmp_list = target_list->list;
2688 pair = (GtkTargetPair *)tmp_list->data;
2689 *p++ = pair->target;
2691 tmp_list = tmp_list->next;
2702 * gtk_selection_data_copy:
2703 * @data: a pointer to a #GtkSelectionData structure.
2705 * Makes a copy of a #GtkSelectionData structure and its data.
2707 * Return value: a pointer to a copy of @data.
2710 gtk_selection_data_copy (GtkSelectionData *data)
2712 GtkSelectionData *new_data;
2714 g_return_val_if_fail (data != NULL, NULL);
2716 new_data = g_new (GtkSelectionData, 1);
2721 new_data->data = g_malloc (data->length + 1);
2722 memcpy (new_data->data, data->data, data->length + 1);
2729 * gtk_selection_data_free:
2730 * @data: a pointer to a #GtkSelectionData structure.
2732 * Frees a #GtkSelectionData structure returned from
2733 * gtk_selection_data_copy().
2736 gtk_selection_data_free (GtkSelectionData *data)
2738 g_return_if_fail (data != NULL);
2741 g_free (data->data);
2747 gtk_selection_data_get_type (void)
2749 static GType our_type = 0;
2752 our_type = g_boxed_type_register_static (I_("GtkSelectionData"),
2753 (GBoxedCopyFunc) gtk_selection_data_copy,
2754 (GBoxedFreeFunc) gtk_selection_data_free);
2760 gtk_selection_bytes_per_item (gint format)
2765 return sizeof (char);
2768 return sizeof (short);
2771 return sizeof (long);
2774 g_assert_not_reached();
2779 #define __GTK_SELECTION_C__
2780 #include "gtkaliasdef.c"