[gtk+/gtk-2-24-quartz: 4/26] Bug 571582: GtkSelection implementation for quartz.



commit 8231c7d1c292c3d24181b42c464c266fa3283a9a
Author: John Ralls <jralls ceridwen us>
Date:   Sun Dec 26 13:48:47 2010 -0800

    Bug 571582: GtkSelection implementation for quartz.

 gdk/quartz/gdkselection-quartz.c |   36 ++-
 gtk/Makefile.am                  |    5 +-
 gtk/gtkquartz.c                  |    1 +
 gtk/gtkselection-quartz.c        |  668 ++++++++++++++++++++++++++++++++++++++
 gtk/gtkselection.c               |   14 +-
 5 files changed, 704 insertions(+), 20 deletions(-)
---
diff --git a/gdk/quartz/gdkselection-quartz.c b/gdk/quartz/gdkselection-quartz.c
index c327eb9..a51f567 100644
--- a/gdk/quartz/gdkselection-quartz.c
+++ b/gdk/quartz/gdkselection-quartz.c
@@ -32,7 +32,8 @@ gdk_selection_owner_set_for_display (GdkDisplay *display,
 				     guint32     time,
 				     gint        send_event)
 {
-  /* FIXME: Implement */
+  g_print ("Not a valid interface on Quartz. Use GtkSelection.\n");
+  g_return_val_if_reached(TRUE);
   return TRUE;
 }
 
@@ -40,7 +41,7 @@ GdkWindow*
 gdk_selection_owner_get_for_display (GdkDisplay *display,
 				     GdkAtom     selection)
 {
-  /* FIXME: Implement */
+ /* Quartz doesn't have an X-selection, so it doesn't have a gdk_selection. */
   return NULL;
 }
 
@@ -50,7 +51,9 @@ gdk_selection_convert (GdkWindow *requestor,
 		       GdkAtom    target,
 		       guint32    time)
 {
-  /* FIXME: Implement */
+  g_print ("Not a valid interface on Quartz. Use GtkSelection.\n");
+  g_return_if_reached();
+
 }
 
 gint
@@ -59,7 +62,8 @@ gdk_selection_property_get (GdkWindow  *requestor,
 			    GdkAtom    *ret_type,
 			    gint       *ret_format)
 {
-  /* FIXME: Implement */
+  g_print ("Quartz windows do not support properties.\n");
+  g_return_val_if_reached(-1);
   return 0;
 }
 
@@ -71,7 +75,8 @@ gdk_selection_send_notify_for_display (GdkDisplay *display,
 				       GdkAtom     property,
 				       guint32     time)
 {
-  /* FIXME: Implement */
+  g_print ("Not a valid interface on Quartz. Use GtkSelection.\n");
+  g_return_if_reached();
 }
 
 gint
@@ -82,8 +87,9 @@ gdk_text_property_to_text_list_for_display (GdkDisplay   *display,
 					    gint          length,
 					    gchar      ***list)
 {
-  /* FIXME: Implement */
-  return 0;
+  /* text and utf8 are equivalent on OSX */
+  return gdk_text_property_to_utf8_list_for_display (display, encoding, format,
+						     text, length, list);
 }
 
 gint
@@ -94,20 +100,21 @@ gdk_string_to_compound_text_for_display (GdkDisplay  *display,
 					 guchar     **ctext,
 					 gint        *length)
 {
-  /* FIXME: Implement */
+  *ctext = (guchar*)g_strdup (str);
+  *length = strlen (str);
   return 0;
 }
 
 void gdk_free_compound_text (guchar *ctext)
 {
-  /* FIXME: Implement */
+  g_free (ctext);
 }
 
 gchar *
 gdk_utf8_to_string_target (const gchar *str)
 {
-  /* FIXME: Implement */
-  return NULL;
+  /* UTF8 is the standard string on OSX */
+  return g_strdup (str);
 }
 
 gboolean
@@ -118,8 +125,11 @@ gdk_utf8_to_compound_text_for_display (GdkDisplay  *display,
 				       guchar     **ctext,
 				       gint        *length)
 {
-  /* FIXME: Implement */
-  return 0;
+  /* We don't use compound text on OSX, just stuff a copy of the string*/
+
+  *ctext = (guchar*)g_strdup (str);
+  *length = strlen (str);
+  return TRUE;
 }
 
 void
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index af494ec..3dae0d8 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -562,7 +562,6 @@ gtk_base_c_sources =            \
 	gtkscalebutton.c	\
 	gtkscrollbar.c		\
 	gtkscrolledwindow.c	\
-	gtkselection.c		\
 	gtkseparator.c		\
 	gtkseparatormenuitem.c	\
 	gtkseparatortoolitem.c	\
@@ -761,11 +760,11 @@ endif
 endif
 
 if USE_QUARTZ
-gtk_clipboard_dnd_c_sources = gtkclipboard-quartz.c gtkdnd-quartz.c gtkquartz.c
+gtk_clipboard_dnd_c_sources = gtkselection.c gtkselection-quartz.c gtkclipboard-quartz.c gtkdnd-quartz.c gtkquartz.c
 gtk_clipboard_dnd_h_sources = gtkquartz.h
 gtk_clipboard_dnd_c_sources_CFLAGS = "-xobjective-c"
 else
-gtk_clipboard_dnd_c_sources = gtkclipboard.c gtkdnd.c
+gtk_clipboard_dnd_c_sources = gtkselection.c gtkclipboard.c gtkdnd.c
 gtk_clipboard_dnd_c_sources_CFLAGS =
 endif
 EXTRA_DIST += gtkquartz.h
diff --git a/gtk/gtkquartz.c b/gtk/gtkquartz.c
index 80b9e87..e452f5b 100644
--- a/gtk/gtkquartz.c
+++ b/gtk/gtkquartz.c
@@ -271,6 +271,7 @@ _gtk_quartz_set_selection_data_for_pasteboard (NSPasteboard     *pasteboard,
 
   type = target_to_pasteboard_type (target);
   g_free (target);
+  g_return_if_fail (data != NULL);
 
   if ([type isEqualTo:NSStringPboardType]) 
     [pasteboard setString:[NSString stringWithUTF8String:(const char *)data]
diff --git a/gtk/gtkselection-quartz.c b/gtk/gtkselection-quartz.c
new file mode 100644
index 0000000..a47d5e1
--- /dev/null
+++ b/gtk/gtkselection-quartz.c
@@ -0,0 +1,668 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* This file implements most of the work of the ICCCM selection protocol.
+ * The code was written after an intensive study of the equivalent part
+ * of John Ousterhout's Tk toolkit, and does many things in much the 
+ * same way.
+ *
+ * The one thing in the ICCCM that isn't fully supported here (or in Tk)
+ * is side effects targets. For these to be handled properly, MULTIPLE
+ * targets need to be done in the order specified. This cannot be
+ * guaranteed with the way we do things, since if we are doing INCR
+ * transfers, the order will depend on the timing of the requestor.
+ *
+ * By Owen Taylor <owt1 cornell edu>	      8/16/97
+ */
+
+/* Terminology note: when not otherwise specified, the term "incr" below
+ * refers to the _sending_ part of the INCR protocol. The receiving
+ * portion is referred to just as "retrieval". (Terminology borrowed
+ * from Tk, because there is no good opposite to "retrieval" in English.
+ * "send" can't be made into a noun gracefully and we're already using
+ * "emission" for something else ....)
+ */
+
+/* The MOTIF entry widget seems to ask for the TARGETS target, then
+   (regardless of the reply) ask for the TEXT target. It's slightly
+   possible though that it somehow thinks we are responding negatively
+   to the TARGETS request, though I don't really think so ... */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include "config.h"
+#include <stdarg.h>
+#include <string.h>
+#include "gdk.h"
+
+#include "gtkmain.h"
+#include "gtkselection.h"
+#include "gtktextbufferrichtext.h"
+#include "gtkintl.h"
+#include "gdk-pixbuf/gdk-pixbuf.h"
+#include "gtkclipboard.h"
+
+#import <Cocoa/Cocoa.h>
+#include "gtkalias.h"
+
+#undef DEBUG_SELECTION
+/*
+ * DON'T USE THIS INTERFACE: USE GTKCLIPBOARD INSTEAD!
+ *
+ * This is the Quartz version of gtkselection. Unlike the other
+ * versions, it was written in 2010, after most code was rewritten to
+ * use GtkClipboard. Quartz, unlike X11, is not a remote-capable
+ * display system, so most of ICCCM is pointless. This implementation
+ * can therefore be much simpler than the X11 implementation. Text is
+ * a lot simpler, too. It's UTF8. No compound text, no legacy
+ * charsets.  There's also only one display, so instead of passing it
+ * around, we'll generally just use gdk_display_get_default() when we
+ * need it.
+ *
+ * There are two constraints: The existing code in various GtkWidgets
+ * which uses GDK_SELECTION_CLIPBOARD (which gtkclipboard-quartz sets
+ * to generalPasteboard) for <ctrl>c copies and GDK_SELECTION_PRIMARY
+ * (for which gtkclipboard-quartz creates a separate pasteboard) for
+ * X-style selection transfers, and Apple's X11 Quartz implementation
+ * which by default puts both on the generalPasteboard. We need to
+ * operate with both.
+ *
+ * IMPORTANT: There is no X11 magic in quartz. If you insist on using
+ * this interface (and you really shouldn't), your MUST connect to
+ * selection-get, selection-received, and selection-clear-event for
+ * your widget.
+ */
+
+/* Maximum size of a sent chunk, in bytes. Also the default size of
+   our buffers */
+
+
+#define IDLE_ABORT_TIME 30
+
+enum {
+  INCR,
+  MULTIPLE,
+  TARGETS,
+  TIMESTAMP,
+  SAVE_TARGETS,
+  LAST_ATOM
+};
+
+typedef struct _GtkSelectionInfo GtkSelectionInfo;
+
+struct _GtkSelectionInfo
+{
+  GdkAtom	 selection;
+  GtkWidget	*owner;	/* widget that owns selection */
+  guint32	 time;		/* time used to acquire selection */
+};
+
+
+/* Local Functions */
+static void gtk_selection_get_cb            (GtkClipboard     *clipboard,
+					     GtkSelectionData *data,
+					     guint             info,
+					     gpointer          widget);
+static void gtk_selection_clear_cb          (GtkClipboard     *clipboard,
+					     gpointer 	       widget);
+static void gtk_selection_default_handler   (GtkWidget        *widget,
+					     GtkSelectionData *data);
+static int  gtk_selection_bytes_per_item    (gint              format);
+static GtkSelectionInfo *gtk_selection_info_get (GdkAtom selection);
+static void gtk_selection_info_remove		(GdkAtom selection,
+						 GtkWidget *owner);
+static void gtk_selection_info_append 		(GdkAtom selection, 
+						 GtkWidget *owner, 
+						 guint32 time);
+static void gtk_selection_info_clear		(GtkWidget *owner);
+static GtkTargetList *gtk_selection_target_list_get (GtkWidget    *widget,
+						     GdkAtom       selection);
+static void gtk_selection_target_list_remove 	    (GtkWidget *widget);
+
+/* Local Data */
+static gint initialize = TRUE;
+static GList *current_selections = NULL;
+
+static GdkAtom gtk_selection_atoms[LAST_ATOM];
+static const char gtk_selection_handler_key[] = "gtk-selection-handlers";
+
+static GtkTargetEntry default_target = {"UTF8_STRING", 0, 1};
+
+/**
+ * gtk_selection_owner_set_for_display:
+ * @display: the #Gdkdisplay where the selection is set
+ * @widget: (allow-none): new selection owner (a #GdkWidget), or %NULL.
+ * @selection: an interned atom representing the selection to claim.
+ * @time_: timestamp with which to claim the selection
+ *
+ * Claim ownership of a given selection for a particular widget, or,
+ * if @widget is %NULL, release ownership of the selection.
+ *
+ * Return value: TRUE if the operation succeeded 
+ * 
+ * Since: 2.2
+ */
+gboolean
+gtk_selection_owner_set_for_display (GdkDisplay   *display,
+				     GtkWidget    *widget,
+				     GdkAtom       selection,
+				     guint32       time)
+{
+  GObject *old_owner;
+  GtkClipboard *clip = gtk_clipboard_get (selection);
+  GtkTargetEntry *targets = &default_target;
+  gint num_targets = 1;
+  GtkTargetList *tlist;
+
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+  g_return_val_if_fail (selection != GDK_NONE, FALSE);
+
+  old_owner = gtk_clipboard_get_owner (clip);
+  if (old_owner)
+    gtk_selection_info_remove (selection, GTK_WIDGET(old_owner));
+
+  if (widget == NULL) 
+    return TRUE;
+
+  g_return_val_if_fail (gtk_widget_get_display (widget) == display, FALSE);
+  
+  if ((tlist = gtk_selection_target_list_get (widget, selection)) != NULL) 
+      targets = gtk_target_table_new_from_list (tlist, &num_targets);
+
+  if (gtk_clipboard_set_with_owner (clip, targets, num_targets,
+				    gtk_selection_get_cb, 
+				    gtk_selection_clear_cb, 
+				    G_OBJECT (widget)))
+    {
+      gtk_selection_info_append (selection, widget, GDK_CURRENT_TIME);
+      return TRUE;
+    }
+  return FALSE;
+}
+
+
+typedef struct _GtkSelectionTargetList GtkSelectionTargetList;
+
+struct _GtkSelectionTargetList {
+  GdkAtom selection;
+  GtkTargetList *list;
+};
+
+/**
+ * gtk_selection_remove_all:
+ * @widget: a #GtkWidget 
+ * 
+ * Removes all handlers and unsets ownership of all 
+ * selections for a widget. Called when widget is being
+ * destroyed. This function will not generally be
+ * called by applications.
+ **/
+void
+gtk_selection_remove_all (GtkWidget *widget)
+{
+  g_return_if_fail(widget == NULL || GTK_IS_WIDGET(widget));
+  gtk_selection_info_clear (widget);
+  /* Remove all selection lists */
+  gtk_selection_target_list_remove (widget);
+}
+
+
+/**
+ * gtk_selection_convert:
+ * @widget: The widget which acts as requestor
+ * @selection: Which selection to get
+ * @target: Form of information desired (e.g., STRING)
+ * @time_: Time of request (usually of triggering event)
+       In emergency, you could use #GDK_CURRENT_TIME
+ * 
+ * Requests the contents of a selection. When received, 
+ * a "selection-received" signal will be generated.
+ * 
+ * Return value: %TRUE if requested succeeded. %FALSE if we could not process
+ *          request. (e.g., there was already a request in process for
+ *          this widget).
+ **/
+gboolean
+gtk_selection_convert (GtkWidget *widget, 
+		       GdkAtom	  selection, 
+		       GdkAtom	  target,
+		       guint32	  time_)
+{
+  GtkClipboard *clip = gtk_clipboard_get (selection);
+  GtkSelectionData *data;
+  
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+  g_return_val_if_fail (selection != GDK_NONE, FALSE);
+  
+  data = gtk_clipboard_wait_for_contents (clip, target);
+  if (data == NULL)
+    return FALSE;
+
+  g_signal_emit_by_name (widget, "selection-received", data, time);
+	  
+  return TRUE;
+}
+
+
+/**
+ * gtk_selection_clear:
+ * @widget: a #GtkWidget
+ * @event: the event
+ * 
+ * The default handler for the #GtkWidget::selection-clear-event
+ * signal. 
+ * 
+ * Return value: %TRUE if the event was handled, otherwise false
+ **/
+gboolean
+gtk_selection_clear (GtkWidget         *widget,
+		     GdkEventSelection *event)
+{
+  gtk_selection_clear_targets (widget, event->selection);
+  return FALSE;
+}
+
+
+/*************************************************************
+ * _gtk_selection_request:
+ *     Handler for "selection_request_event" 
+ *   arguments:
+ *     widget:
+ *     event:
+ *   results:
+ *************************************************************/
+
+gboolean
+_gtk_selection_request (GtkWidget *widget,
+			GdkEventSelection *event)
+{
+  g_print ("Selection Request Events should not occur in quartz\n");  
+  return TRUE;
+}
+
+/*************************************************************
+ * _gtk_selection_incr_event:
+ *     Called whenever an PropertyNotify event occurs for an 
+ *     GdkWindow with user_data == NULL. These will be notifications
+ *     that a window we are sending the selection to via the
+ *     INCR protocol has deleted a property and is ready for
+ *     more data.
+ *
+ *   arguments:
+ *     window:	the requestor window
+ *     event:	the property event structure
+ *
+ *   results:
+ *************************************************************/
+
+gboolean
+_gtk_selection_incr_event (GdkWindow	   *window,
+			   GdkEventProperty *event)
+{
+  g_print ("Selection_INCR_Events should not occur in quartz\n");  
+  return TRUE;
+}
+
+/*************************************************************
+ * _gtk_selection_notify:
+ *     Handler for "selection-notify-event" signals on windows
+ *     where a retrieval is currently in process. The selection
+ *     owner has responded to our conversion request.
+ *   arguments:
+ *     widget:		Widget getting signal
+ *     event:		Selection event structure
+ *     info:		Information about this retrieval
+ *   results:
+ *     was event handled?
+ *************************************************************/
+
+gboolean
+_gtk_selection_notify (GtkWidget	       *widget,
+		       GdkEventSelection *event)
+{
+  g_print ("Selection_Notifications should not occur in quartz\n");  
+  
+  return TRUE;
+}
+
+/*************************************************************
+ * _gtk_selection_property_notify:
+ *     Handler for "property-notify-event" signals on windows
+ *     where a retrieval is currently in process. The selection
+ *     owner has added more data.
+ *   arguments:
+ *     widget:		Widget getting signal
+ *     event:		Property event structure
+ *     info:		Information about this retrieval
+ *   results:
+ *     was event handled?
+ *************************************************************/
+
+gboolean
+_gtk_selection_property_notify (GtkWidget	*widget,
+				GdkEventProperty *event)
+{
+  g_print ("Selection_Property_Notifications should not occur in quartz\n");  
+  return TRUE;
+}
+
+
+/*************************************************************
+ * gtk_selection_get_cb()
+ * @clipboard: The clipboard requesting the data
+ * @data: Pass to selection-get signal; handlers should put requested
+ * data in the structure pointed to.
+ * @info: DND uses this on Windows and X11. It can be ignored for
+ * normal selection use.
+ * @owner: The window to which the information request is sent; it's
+ * the owner set with gtk_selection_owner_set_for_display.
+ *
+ * Emits a signal to the owner window to fill in the provided data structure.
+ *************************************************************/
+/* GtkClipboardGetFunc */
+static void
+gtk_selection_get_cb (GtkClipboard* clipboard,
+		      GtkSelectionData *data,
+		      guint info,
+		      gpointer owner)
+{
+  GtkTargetList *target_list;
+  GtkWidget *widget = GTK_WIDGET (owner);
+  
+
+  g_return_if_fail (widget != NULL);
+
+  target_list = gtk_selection_target_list_get (widget, data->selection);
+
+  if ( data->target == gtk_selection_atoms[TIMESTAMP] ||
+       data->target == gtk_selection_atoms[TARGETS] ||
+       data->target == gtk_selection_atoms[SAVE_TARGETS])
+    {
+      gtk_selection_default_handler (widget, data);
+      return;
+    }
+  if (target_list &&
+      gtk_target_list_find (target_list, data->target, &info))
+    {
+      g_signal_emit_by_name (widget,
+			     "selection-get",
+			     data,
+			     info, time);
+    }
+}
+
+static void
+gtk_selection_clear_cb (GtkClipboard* clipboard,
+			gpointer owner)
+{
+  GtkWidget *widget = GTK_WIDGET (owner);
+  GdkEventSelection event;
+  event.type = GDK_SELECTION_CLEAR;
+  event.selection = GDK_SELECTION_PRIMARY;
+  event.window = gtk_widget_get_window(widget);
+  g_signal_emit_by_name (widget,
+			 "selection-clear-event",
+			 &event,
+			 NULL);
+}
+
+/*************************************************************
+ * gtk_selection_default_handler:
+ *     Handles some default targets that exist for any widget
+ *     If it can't fit results into buffer, returns -1. This
+ *     won't happen in any conceivable case, since it would
+ *     require 1000 selection targets!
+ *
+ *   arguments:
+ *     widget:	    selection owner
+ *     data:	    selection data [INOUT]
+ *
+ *************************************************************/
+
+static void
+gtk_selection_default_handler (GtkWidget	*widget,
+			       GtkSelectionData *data)
+{
+  if (data->target == gtk_selection_atoms[TIMESTAMP])
+    {
+      /* Time which was used to obtain selection */
+      GList *tmp_list;
+      GtkSelectionInfo *selection_info;
+      
+      tmp_list = current_selections;
+      while (tmp_list)
+	{
+	  selection_info = (GtkSelectionInfo *)tmp_list->data;
+	  if ((selection_info->owner == widget) &&
+	      (selection_info->selection == data->selection))
+	    {
+	      gulong time = selection_info->time;
+
+	      gtk_selection_data_set (data,
+				      GDK_SELECTION_TYPE_INTEGER,
+				      32,
+				      (guchar *)&time,
+				      sizeof (time));
+	      return;
+	    }
+	  
+	  tmp_list = tmp_list->next;
+	}
+      
+      data->length = -1;
+    }
+  else if (data->target == gtk_selection_atoms[TARGETS])
+    {
+      /* List of all targets supported for this widget/selection pair */
+      GdkAtom *p;
+      guint count;
+      GList *tmp_list;
+      GtkTargetList *target_list;
+      GtkTargetPair *pair;
+      
+      target_list = gtk_selection_target_list_get (widget,
+						   data->selection);
+      count = g_list_length (target_list->list) + 3;
+      
+      data->type = GDK_SELECTION_TYPE_ATOM;
+      data->format = 32;
+      data->length = count * sizeof (GdkAtom);
+
+      /* selection data is always terminated by a trailing \0
+       */
+      p = g_malloc (data->length + 1);
+      data->data = (guchar *)p;
+      data->data[data->length] = '\0';
+      
+      *p++ = gtk_selection_atoms[TIMESTAMP];
+      *p++ = gtk_selection_atoms[TARGETS];
+      *p++ = gtk_selection_atoms[MULTIPLE];
+      
+      tmp_list = target_list->list;
+      while (tmp_list)
+	{
+	  pair = (GtkTargetPair *)tmp_list->data;
+	  *p++ = pair->target;
+	  
+	  tmp_list = tmp_list->next;
+	}
+    }
+  else if (data->target == gtk_selection_atoms[SAVE_TARGETS])
+    {
+      gtk_selection_data_set (data,
+			      gdk_atom_intern_static_string ("NULL"),
+			      32, NULL, 0);
+    }
+  else
+    {
+      data->length = -1;
+    }
+}
+
+static GtkSelectionInfo *
+gtk_selection_info_get (GdkAtom selection) 
+{
+  GList *tmp_list;
+  GList *next;
+  GtkSelectionInfo *selection_info;
+
+  tmp_list = current_selections;
+  while (tmp_list)
+    {
+      next = tmp_list->next;
+      selection_info = (GtkSelectionInfo *)tmp_list->data;
+      
+      if (selection_info->selection == selection)
+	{	
+	  return selection_info;
+	}
+      
+      tmp_list = next;
+    }
+  return NULL;
+}
+
+static void
+gtk_selection_info_remove (GdkAtom selection, GtkWidget *owner)
+{
+  GList *tmp_list;
+  GList *next;
+  GtkSelectionInfo *selection_info;
+
+  g_return_if_fail (GTK_IS_WIDGET (owner));
+
+  tmp_list = current_selections;
+  while (tmp_list)
+    {
+      next = tmp_list->next;
+      selection_info = (GtkSelectionInfo *)tmp_list->data;
+      
+      if (selection_info->selection == selection &&
+	  selection_info->owner == owner)
+	{	
+	  current_selections = g_list_remove_link (current_selections,
+						   tmp_list);
+	  g_list_free (tmp_list);
+	  g_slice_free (GtkSelectionInfo, selection_info);
+	  return;
+	}
+      
+      tmp_list = next;
+    }
+}
+static void 
+gtk_selection_info_append (GdkAtom selection, GtkWidget *owner, guint32 time)
+{
+  GtkSelectionInfo *selection_info;
+
+  g_return_if_fail (GTK_IS_WIDGET (owner));
+
+  selection_info = g_slice_new (GtkSelectionInfo);
+  selection_info->selection = selection;
+  selection_info->owner = owner;
+  selection_info->time = time;
+  current_selections = g_list_prepend (current_selections,
+				       selection_info);
+}
+
+static void
+gtk_selection_info_clear (GtkWidget *owner)
+{
+  GList *tmp_list;
+  GList *next;
+  GtkSelectionInfo *selection_info;
+
+  g_return_if_fail (GTK_IS_WIDGET (owner));
+
+  tmp_list = current_selections;
+  while (tmp_list)
+    {
+      next = tmp_list->next;
+      selection_info = (GtkSelectionInfo *)tmp_list->data;
+      
+      if (selection_info->owner == owner)
+	{	
+	  current_selections = g_list_remove_link (current_selections,
+						   tmp_list);
+	  g_list_free (tmp_list);
+	  g_slice_free (GtkSelectionInfo, selection_info);
+	}
+      
+      tmp_list = next;
+    }
+}
+
+static GtkTargetList *
+gtk_selection_target_list_get (GtkWidget    *widget,
+			       GdkAtom       selection)
+{
+  GtkSelectionTargetList *sellist;
+  GList *tmp_list;
+  GList *lists;
+
+  lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
+  
+  tmp_list = lists;
+  while (tmp_list)
+    {
+      sellist = tmp_list->data;
+      if (sellist->selection == selection)
+	return sellist->list;
+      tmp_list = tmp_list->next;
+    }
+
+  sellist = g_slice_new (GtkSelectionTargetList);
+  sellist->selection = selection;
+  sellist->list = gtk_target_list_new (NULL, 0);
+
+  lists = g_list_prepend (lists, sellist);
+  g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), lists);
+
+  return sellist->list;
+}
+
+static void
+gtk_selection_target_list_remove (GtkWidget *widget)
+{
+  GtkSelectionTargetList *sellist;
+  GList *tmp_list;
+  GList *lists;
+
+  lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key);
+  
+  tmp_list = lists;
+  while (tmp_list)
+    {
+      sellist = tmp_list->data;
+
+      gtk_target_list_unref (sellist->list);
+
+      g_slice_free (GtkSelectionTargetList, sellist);
+      tmp_list = tmp_list->next;
+    }
+
+  g_list_free (lists);
+  g_object_set_data (G_OBJECT (widget), I_(gtk_selection_handler_key), NULL);
+}
+
diff --git a/gtk/gtkselection.c b/gtk/gtkselection.c
index 5b3ae1d..716411f 100644
--- a/gtk/gtkselection.c
+++ b/gtk/gtkselection.c
@@ -633,6 +633,7 @@ gtk_target_table_free (GtkTargetEntry *targets,
   g_free (targets);
 }
 
+#ifndef GDK_WINDOWING_QUARTZ /* Quartz handled by gtkselection-quartz.c */
 /**
  * gtk_selection_owner_set_for_display:
  * @display: the #Gdkdisplay where the selection is set
@@ -735,7 +736,7 @@ gtk_selection_owner_set_for_display (GdkDisplay   *display,
   else
     return FALSE;
 }
-
+#endif /* GDK_WINDOWING_QUARTZ */
 /**
  * gtk_selection_owner_set:
  * @widget: (allow-none):  a #GtkWidget, or %NULL.
@@ -937,7 +938,7 @@ gtk_selection_add_targets (GtkWidget            *widget,
 #endif
 }
 
-
+#ifndef GDK_WINDOWING_QUARTZ /* Quartz is handled in gtkselection-quartz.c */
 /**
  * gtk_selection_remove_all:
  * @widget: a #GtkWidget 
@@ -998,8 +999,9 @@ gtk_selection_remove_all (GtkWidget *widget)
   /* Remove all selection lists */
   gtk_selection_target_list_remove (widget);
 }
+#endif /* GDK_WINDOWING_QUARTZ */
 
-
+#ifndef GDK_WINDOWING_QUARTZ /* Quartz is handled in gtkselection-quartz.c */
 /**
  * gtk_selection_convert:
  * @widget: The widget which acts as requestor
@@ -1111,7 +1113,7 @@ gtk_selection_convert (GtkWidget *widget,
   
   return TRUE;
 }
-
+#endif /* GDK_WINDOWING_QUARTZ */
 /**
  * gtk_selection_data_get_selection:
  * @selection_data: a pointer to a #GtkSelectionData structure.
@@ -2176,6 +2178,7 @@ gtk_selection_init (void)
   initialize = FALSE;
 }
 
+#ifndef GDK_WINDOWING_QUARTZ /* Quartz handled by gtkselection-quartz.c */
 /**
  * gtk_selection_clear:
  * @widget: a #GtkWidget
@@ -2610,6 +2613,7 @@ _gtk_selection_incr_event (GdkWindow	   *window,
   
   return TRUE;
 }
+#endif /* GDK_WINDOWING_QUARTZ */
 
 /*************************************************************
  * gtk_selection_incr_timeout:
@@ -2664,6 +2668,7 @@ gtk_selection_incr_timeout (GtkIncrInfo *info)
   return retval;
 }
 
+#ifndef GDK_WINDOWING_QUARTZ /* Quartz handled by gtkselection-quartz.c */
 /*************************************************************
  * _gtk_selection_notify:
  *     Handler for "selection-notify-event" signals on windows
@@ -2857,6 +2862,7 @@ _gtk_selection_property_notify (GtkWidget	*widget,
   
   return TRUE;
 }
+#endif /* GDK_WINDOWING_QUARTZ */
 
 /*************************************************************
  * gtk_selection_retrieval_timeout:



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]