gtk+ r22255 - in trunk: . gdk/win32



Author: tml
Date: Fri Jan 30 01:16:47 2009
New Revision: 22255
URL: http://svn.gnome.org/viewvc/gtk+?rev=22255&view=rev

Log:
2009-01-29  Tor Lillqvist  <tml novell com>

	Bug 559408 - Transparency lost when images are copied between GTK+
	and the clipboard on Windows

	The code in gdkselection-win32.c is simplified quite a lot. When
	an image is stored on the clipboard from GTK+, only the "PNG" and
	CF_DIB formats are advertised. PNG is our preferred format because
	it can losslessly represent any image that gdk-pixbuf can handle,
	even with alpha, unambiguously. CF_DIB is also advertised because
	of its ubiquitous support in Windows software.

	Delayed rendering is used as before, so for other data than text
	nothing is actually stored on the clipboard until some app asks
	for it.

	It's pointless to advertise images formats like "image/png" or
	"image/x-MS-bmp" that no other Windows application is going to
	look for anyway. Likewise it's pointless to store text under
	formats like "text/plain" or "UTF8_STRING". Just store
	CF_UNICODETEXT. CF_TEXT will be available as a synthesized format
	anyways.

	Office 2007 offers and asks for images in PNG format using the
	registered clipboard format name "PNG", so we do likewise. If the
	"PNG" format is available that is preferred when copying to GTK+
	from the clipboard.

	Unfortunately Word 2007 still uses CF_DIB without handling
	alpha. But PowerPoint 2007 uses PNG if available and handles alpha
	correctly. Both Word and Powerpoint offer PNG with alpha nicely.

	Firefox and IE7 offer images that contain alpha as 32-bit version
	3 BI_RGB DIBs with the undocumented "extra" bytes actually being
	alpha. Also, alpha is premultiplied into the RGB bytes, presumably
	because that is how AlphaBlend() wants such DIBs. That is also
	taken care of. At least for Firefox it easy to be sure that a
	CF_DIB on the clipboard is from Firefox.

	Also some general stylistic cleanup, comment improvements, and
	improvements of debugging printout especially in the clipboard
	handling. Those are not detailled below.

	* gdk/win32/gdkprivate-win32.h
	* gdk/win32/gdkglobals-win32.c
	* gdk/win32/gdkgmain-win32.c: Move some globals that were used
	only in gdkselection-win32.c to be local to that file.

	* gdk/win32/gdkproperty-win32.c (gdk_property_change): Don't
	bother checking if text to be placed on the clipboard consists of
	only ASCII.

	* gdk/win32/gdkselection-win32.c: Add static variables for a list
	of GdkPixbuf-supported formats, well-known registered clipboard
	formats for images, and for GdkAtoms for well-known image and text
	formats.

	(_gdk_win32_selection_init): Initialize above static variables.

	(selection_property_store) (gdk_selection_property_get)
	(_gdk_selection_property_delete): Don't use a FIFO of GdkSelProps
	for a window after all, it breaks testtext. See bug #163844.

	(gdk_selection_convert): When converting to the TARGETS format,
	i.e. when the caller wants to know what clipboard formats are
	available, if PNG is available we report just that and skip
	CF_DIB, JPEG and GIF even if advertised.

	If CF_UNICODETEXT is available, report only UTF8_STRING.

	When converting to the UTF8_STRING format, i.e. when the caller
	wants text from the clipboard, try just CF_UNICODETEXT. There is
	no point in trying CF_TEXT as Windows will synthesize
	CF_UNICODETEXT from CF_TEXT anyway, if some app has stored just
	CF_TEXT.

	When converting to the image/bmp format, i.e. when the caller
	wants an CF_DIB image from the clipboard, we check if the DIB is a
	version 3 32-bit BI_RGB one that is likely to actually contain
	alpha in the "extra" bytes. Such a DIB is likely to have
	premultiplied alpha even, at least in the case of Firefox 3 and
	IE7. We then edit the DIB in-place into a version 5 one in
	BI_BITFIELDS format and undo the alpha premultiplication.

	In any case, prepend a BMP file header before letting go of the
	data which will be fed to the gdk-pixbuf bmp loader by upper
	levels.

	(gdk_win32_selection_add_targets): If some kind of pixmap image
	format is being added, actually advertise just PNG and
	CF_DIB. Note that alpha won't be stored on the clipboard through
	CF_DIB. This is because gdk-pixbuf's bmp loader doesn't save
	alpha. Furthermore, few if any non-GTK+ Windows apps seem to
	understand a version 5 DIB with proper alpha anyway.

	(_gdk_win32_selection_convert_to_dib): Simplified muchly.




Modified:
   trunk/ChangeLog
   trunk/gdk/win32/gdkevents-win32.c
   trunk/gdk/win32/gdkglobals-win32.c
   trunk/gdk/win32/gdkmain-win32.c
   trunk/gdk/win32/gdkprivate-win32.h
   trunk/gdk/win32/gdkproperty-win32.c
   trunk/gdk/win32/gdkselection-win32.c

Modified: trunk/gdk/win32/gdkevents-win32.c
==============================================================================
--- trunk/gdk/win32/gdkevents-win32.c	(original)
+++ trunk/gdk/win32/gdkevents-win32.c	Fri Jan 30 01:16:47 2009
@@ -694,12 +694,12 @@
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
   
-  GDK_NOTE (EVENTS, g_print ("gdk_keyboard_grab %p\n",
-			     GDK_WINDOW_HWND (window)));
+  GDK_NOTE (EVENTS, g_print ("gdk_keyboard_grab %p%s\n",
+			     GDK_WINDOW_HWND (window), owner_events ? " OWNER_EVENTS" : ""));
 
   if (!GDK_WINDOW_DESTROYED (window))
     {
-      k_grab_owner_events = owner_events != 0;
+      k_grab_owner_events = owner_events;
       return_val = GDK_GRAB_SUCCESS;
     }
   else
@@ -746,7 +746,7 @@
 
   g_return_if_fail (display == _gdk_display);
 
-  GDK_NOTE (EVENTS, g_print ("gdk_keyboard_ungrab\n"));
+  GDK_NOTE (EVENTS, g_print ("gdk_display_keyboard_ungrab\n"));
 
   if (k_grab_window && !k_grab_owner_events)
     {
@@ -955,6 +955,7 @@
 print_event (GdkEvent *event)
 {
   gchar *escaped, *kvname;
+  gchar *selection_name, *target_name, *property_name;
 
   g_print ("%s%*s===> ", (debug_indent > 0 ? "\n" : ""), debug_indent, "");
   switch (event->any.type)
@@ -1065,6 +1066,18 @@
     case GDK_FOCUS_CHANGE:
       g_print ("%s", (event->focus_change.in ? "IN" : "OUT"));
       break;
+    case GDK_SELECTION_REQUEST:
+    case GDK_SELECTION_NOTIFY:
+    case GDK_SELECTION_CLEAR:
+      selection_name = gdk_atom_name (event->selection.selection);
+      target_name = gdk_atom_name (event->selection.target);
+      property_name = gdk_atom_name (event->selection.property);
+      g_print ("sel:%s tgt:%s prop:%s",
+	       selection_name, target_name, property_name);
+      g_free (selection_name);
+      g_free (target_name);
+      g_free (property_name);
+      break;
     case GDK_CONFIGURE:
       g_print ("x:%d y:%d w:%d h:%d",
 	       event->configure.x, event->configure.y,
@@ -1682,7 +1695,8 @@
 
 /* The check_extended flag controls whether to check if the windows want
  * events from extended input devices and if the message should be skipped
- * because an extended input device is active */
+ * because an extended input device is active
+ */
 static gboolean
 propagate (GdkWindow  **window,
 	   MSG         *msg,
@@ -1693,14 +1707,13 @@
 					 MSG *msg),
 	   gboolean    	check_extended)
 {
-  gboolean in_propagation = FALSE;
-
   if (grab_window != NULL && !grab_owner_events)
     {
       /* Event source is grabbed with owner_events FALSE */
 
-      /* See if the event should be ignored because an extended input device
-       * is used */
+      /* See if the event should be ignored because an extended input
+       * device is used
+       */
       if (check_extended &&
 	  ((GdkWindowObject *) grab_window)->extension_events != 0 &&
 	  _gdk_input_ignore_core)
@@ -1720,10 +1733,12 @@
 	  return TRUE;
 	}
     }
+
+  /* If we come here, we know that if grab_window != NULL then
+   * grab_owner_events is TRUE
+   */
   while (TRUE)
     {
-      /* See if the event should be ignored because an extended input device
-       * is used */
       if (check_extended &&
 	  ((GdkWindowObject *) *window)->extension_events != 0 &&
 	  _gdk_input_ignore_core)
@@ -1742,8 +1757,6 @@
 		{
 		  /* Event source is grabbed with owner_events TRUE */
 
-		  /* See if the event should be ignored because an extended
-		   * input device is used */
 		  if (check_extended &&
 		      ((GdkWindowObject *) grab_window)->extension_events != 0 &&
 		      _gdk_input_ignore_core)
@@ -1774,7 +1787,6 @@
 	  else
 	    {
 	      assign_object (window, parent);
-	      in_propagation = TRUE;
 	      /* The only branch where we actually continue the loop */
 	    }
 	}
@@ -2867,7 +2879,7 @@
       break;
 
     case WM_MOUSEWHEEL:
-      GDK_NOTE (EVENTS, g_print (" %d", HIWORD (msg->wParam)));
+      GDK_NOTE (EVENTS, g_print (" %d", (short) HIWORD (msg->wParam)));
 
       /* WM_MOUSEWHEEL is delivered to the focus window. Work around
        * that. Also, the position is in screen coordinates, not client
@@ -2917,6 +2929,42 @@
       return_val = TRUE;
       break;
 
+    case WM_HSCROLL:
+      GDK_NOTE (EVENTS,
+		(g_print (" %s",
+			  (LOWORD (msg->wParam) == SB_ENDSCROLL ? "ENDSCROLL" :
+			   (LOWORD (msg->wParam) == SB_LEFT ? "LEFT" :
+			    (LOWORD (msg->wParam) == SB_RIGHT ? "RIGHT" :
+			     (LOWORD (msg->wParam) == SB_LINELEFT ? "LINELEFT" :
+			      (LOWORD (msg->wParam) == SB_LINERIGHT ? "LINERIGHT" :
+			       (LOWORD (msg->wParam) == SB_PAGELEFT ? "PAGELEFT" :
+				(LOWORD (msg->wParam) == SB_PAGERIGHT ? "PAGERIGHT" :
+				 (LOWORD (msg->wParam) == SB_THUMBPOSITION ? "THUMBPOSITION" :
+				  (LOWORD (msg->wParam) == SB_THUMBTRACK ? "THUMBTRACK" :
+				   "???")))))))))),
+		 (LOWORD (msg->wParam) == SB_THUMBPOSITION ||
+		  LOWORD (msg->wParam) == SB_THUMBTRACK) ?
+		 g_print (" %d", HIWORD (msg->wParam)) : 0));
+      break;
+
+    case WM_VSCROLL:
+      GDK_NOTE (EVENTS,
+		(g_print (" %s",
+			  (LOWORD (msg->wParam) == SB_ENDSCROLL ? "ENDSCROLL" :
+			   (LOWORD (msg->wParam) == SB_BOTTOM ? "BOTTOM" :
+			    (LOWORD (msg->wParam) == SB_TOP ? "TOP" :
+			     (LOWORD (msg->wParam) == SB_LINEDOWN ? "LINDOWN" :
+			      (LOWORD (msg->wParam) == SB_LINEUP ? "LINEIP" :
+			       (LOWORD (msg->wParam) == SB_PAGEDOWN ? "PAGEDOWN" :
+				(LOWORD (msg->wParam) == SB_PAGEUP ? "PAGEUP" :
+				 (LOWORD (msg->wParam) == SB_THUMBPOSITION ? "THUMBPOSITION" :
+				  (LOWORD (msg->wParam) == SB_THUMBTRACK ? "THUMBTRACK" :
+				   "???")))))))))),
+		 (LOWORD (msg->wParam) == SB_THUMBPOSITION ||
+		  LOWORD (msg->wParam) == SB_THUMBTRACK) ?
+		 g_print (" %d", HIWORD (msg->wParam)) : 0));
+      break;
+
     case WM_QUERYNEWPALETTE:
       if (gdk_visual_get_system ()->type == GDK_VISUAL_PSEUDO_COLOR)
 	{
@@ -3608,7 +3656,7 @@
 	  event->selection.send_event = FALSE;
 	  event->selection.selection = GDK_SELECTION_CLIPBOARD;
 	  event->selection.target = target;
-	  event->selection.property = _gdk_selection_property;
+	  event->selection.property = _gdk_selection;
 	  event->selection.requestor = msg->hwnd;
 	  event->selection.time = msg->time;
 
@@ -3640,6 +3688,11 @@
 	      /* The requestor is holding the clipboard, no
 	       * OpenClipboard() is required/possible
 	       */
+	      GDK_NOTE (DND,
+			g_print (" SetClipboardData(%s,%p)",
+				 _gdk_win32_cf_to_string (msg->wParam),
+				 _delayed_rendering_data));
+
 	      API_CALL (SetClipboardData, (msg->wParam, _delayed_rendering_data));
 	      _delayed_rendering_data = NULL;
 	    }
@@ -3679,7 +3732,6 @@
       GDK_NOTE (EVENTS, g_print (" %s thread: %I64d",
 				 msg->wParam ? "YES" : "NO",
 				 (gint64) msg->lParam));
-
       if (msg->wParam && GDK_WINDOW_IS_MAPPED (window))
 	ensure_stacking_on_activate_app (msg, window);
       break;

Modified: trunk/gdk/win32/gdkglobals-win32.c
==============================================================================
--- trunk/gdk/win32/gdkglobals-win32.c	(original)
+++ trunk/gdk/win32/gdkglobals-win32.c	Fri Jan 30 01:16:47 2009
@@ -46,10 +46,7 @@
 gboolean	  _gdk_input_locale_is_ime;
 UINT		  _gdk_input_codepage;
 
-WORD		  _cf_utf8_string;
-WORD		  _cf_image_bmp;
-
-GdkAtom           _gdk_selection_property;
+GdkAtom           _gdk_selection;
 GdkAtom	          _wm_transient_for;
 GdkAtom		  _targets;
 GdkAtom		  _save_targets;
@@ -57,7 +54,6 @@
 GdkAtom		  _text;
 GdkAtom		  _compound_text;
 GdkAtom		  _text_uri_list;
-GdkAtom		  _image_bmp;
 
 GdkAtom		  _local_dnd;
 GdkAtom		  _gdk_win32_dropfiles;

Modified: trunk/gdk/win32/gdkmain-win32.c
==============================================================================
--- trunk/gdk/win32/gdkmain-win32.c	(original)
+++ trunk/gdk/win32/gdkmain-win32.c	Fri Jan 30 01:16:47 2009
@@ -100,10 +100,7 @@
 
   CoInitialize (NULL);
 
-  _cf_utf8_string = RegisterClipboardFormat ("UTF8_STRING");
-  _cf_image_bmp = RegisterClipboardFormat ("image/bmp");
-
-  _gdk_selection_property = gdk_atom_intern ("GDK_SELECTION", FALSE);
+  _gdk_selection = gdk_atom_intern ("GDK_SELECTION", FALSE);
   _wm_transient_for = gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE);
   _targets = gdk_atom_intern ("TARGETS", FALSE);
   _save_targets = gdk_atom_intern ("SAVE_TARGETS", FALSE);
@@ -111,7 +108,6 @@
   _text = gdk_atom_intern ("TEXT", FALSE);
   _compound_text = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
   _text_uri_list = gdk_atom_intern ("text/uri-list", FALSE);
-  _image_bmp = gdk_atom_intern ("image/bmp", FALSE);
 
   _local_dnd = gdk_atom_intern ("LocalDndSelection", FALSE);
   _gdk_win32_dropfiles = gdk_atom_intern ("DROPFILES_DND", FALSE);
@@ -1039,9 +1035,7 @@
 #define CASE(x) case CF_##x: return "CF_" #x
       CASE (BITMAP);
       CASE (DIB);
-#ifdef CF_DIBV5
       CASE (DIBV5);
-#endif
       CASE (DIF);
       CASE (DSPBITMAP);
       CASE (DSPENHMETAFILE);

Modified: trunk/gdk/win32/gdkprivate-win32.h
==============================================================================
--- trunk/gdk/win32/gdkprivate-win32.h	(original)
+++ trunk/gdk/win32/gdkprivate-win32.h	Fri Jan 30 01:16:47 2009
@@ -93,6 +93,11 @@
 #define WM_APPCOMMAND 0x319
 #endif
 
+#ifndef CF_DIBV5
+#define CF_DIBV5 17
+#endif
+
+
 /* Define some combinations of GdkDebugFlags */
 #define GDK_DEBUG_EVENTS_OR_COLORMAP (GDK_DEBUG_EVENTS|GDK_DEBUG_COLORMAP)
 #define GDK_DEBUG_EVENTS_OR_INPUT (GDK_DEBUG_EVENTS|GDK_DEBUG_INPUT)
@@ -400,12 +405,8 @@
 extern gboolean		 _gdk_keyboard_has_altgr;
 extern guint		 _scancode_rshift;
 
-/* Registered clipboard formats */
-extern WORD		 _cf_utf8_string;
-extern WORD		 _cf_image_bmp;
-
 /* GdkAtoms: properties, targets and types */
-extern GdkAtom		 _gdk_selection_property;
+extern GdkAtom		 _gdk_selection;
 extern GdkAtom		 _wm_transient_for;
 extern GdkAtom		 _targets;
 extern GdkAtom		 _save_targets;
@@ -413,7 +414,6 @@
 extern GdkAtom		 _text;
 extern GdkAtom		 _compound_text;
 extern GdkAtom		 _text_uri_list;
-extern GdkAtom		 _image_bmp;
 
 /* DND selections */
 extern GdkAtom           _local_dnd;

Modified: trunk/gdk/win32/gdkproperty-win32.c
==============================================================================
--- trunk/gdk/win32/gdkproperty-win32.c	(original)
+++ trunk/gdk/win32/gdkproperty-win32.c	Fri Jan 30 01:16:47 2009
@@ -99,7 +99,8 @@
   ATOM win32_atom;
   gchar name[256];
 
-  if (GDK_SELECTION_PRIMARY == atom) return g_strdup ("PRIMARY");
+  if (GDK_NONE == atom) return g_strdup ("<none>");
+  else if (GDK_SELECTION_PRIMARY == atom) return g_strdup ("PRIMARY");
   else if (GDK_SELECTION_SECONDARY == atom) return g_strdup ("SECONDARY");
   else if (GDK_SELECTION_CLIPBOARD == atom) return g_strdup ("CLIPBOARD");
   else if (GDK_SELECTION_TYPE_ATOM == atom) return g_strdup ("ATOM");
@@ -153,14 +154,10 @@
 		     gint          nelements)
 {
   HGLOBAL hdata;
-  UINT cf = 0;
-  gint i, size, nchars;
-  gchar *prop_name, *type_name;
+  gint i, size;
   guchar *ucptr, *buf = NULL;
-  wchar_t *wcptr;
+  wchar_t *wcptr, *p;
   glong wclen;
-  enum { SYSTEM_CODEPAGE, UNICODE_TEXT } method;
-  gboolean ok = TRUE;
 
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
@@ -168,21 +165,23 @@
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  GDK_NOTE (DND,
-	    (prop_name = gdk_atom_name (property),
-	     type_name = gdk_atom_name (type),
-	     g_print ("gdk_property_change: %p %p (%s) %p (%s) %s %d*%d bytes: %s\n",
-		      GDK_WINDOW_HWND (window),
-		      property, prop_name,
-		      type, type_name,
-		      (mode == GDK_PROP_MODE_REPLACE ? "REPLACE" :
-		       (mode == GDK_PROP_MODE_PREPEND ? "PREPEND" :
-			(mode == GDK_PROP_MODE_APPEND ? "APPEND" :
-			 "???"))),
-		      format, nelements,
-		      _gdk_win32_data_to_string (data, MIN (10, format*nelements/8))),
-	     g_free (prop_name),
-	     g_free (type_name)));
+  GDK_NOTE (DND, {
+      gchar *prop_name = gdk_atom_name (property);
+      gchar *type_name = gdk_atom_name (type);
+      
+      g_print ("gdk_property_change: %p %s %s %s %d*%d bits: %s\n",
+	       GDK_WINDOW_HWND (window),
+	       prop_name,
+	       type_name,
+	       (mode == GDK_PROP_MODE_REPLACE ? "REPLACE" :
+		(mode == GDK_PROP_MODE_PREPEND ? "PREPEND" :
+		 (mode == GDK_PROP_MODE_APPEND ? "APPEND" :
+		  "???"))),
+	       format, nelements,
+	       _gdk_win32_data_to_string (data, MIN (10, format*nelements/8)));
+      g_free (prop_name);
+      g_free (type_name);
+    });
 
   /* We should never come here for these types */
   g_return_if_fail (type != GDK_TARGET_STRING);
@@ -190,9 +189,9 @@
   g_return_if_fail (type != _compound_text);
   g_return_if_fail (type != _save_targets);
 
-  if (property == _gdk_selection_property
-      && format == 8
-      && mode == GDK_PROP_MODE_REPLACE)
+  if (property == _gdk_selection &&
+      format == 8 &&
+      mode == GDK_PROP_MODE_REPLACE)
     {
       if (type == _utf8_string)
 	{
@@ -202,38 +201,13 @@
 	      return;
 	    }
 
-	  nchars = g_utf8_strlen ((char*) data, nelements);
-
-	  /* Check if only ASCII */
-	  for (i = 0; i < nelements; i++)
-	    if (data[i] >= 0200)
-	      break;
-
-	  if (i == nelements)
-	    {
-	      /* If only ASCII, use CF_TEXT and the data as such */
-	      method = SYSTEM_CODEPAGE;
-	      size = nelements;
-	      for (i = 0; i < nelements; i++)
-		if (data[i] == '\n')
-		  size++;
-	      size++;
-	      GDK_NOTE (DND, g_print ("... as text: %.40s\n", data));
-	    }
-	  else
-	    {
-	      /* Use CF_UNICODETEXT */
-	      method = UNICODE_TEXT;
-
-	      wcptr = g_utf8_to_utf16 ((char *) data, nelements, NULL, &wclen, NULL);
+	  wcptr = g_utf8_to_utf16 ((char *) data, nelements, NULL, &wclen, NULL);
 
-	      wclen++;		/* Terminating 0 */
-	      size = wclen * 2;
-	      for (i = 0; i < wclen; i++)
-		if (wcptr[i] == '\n')
-		  size += 2;
-	      GDK_NOTE (DND, g_print ("... as Unicode\n"));
-	    }
+	  wclen++;		/* Terminating 0 */
+	  size = wclen * 2;
+	  for (i = 0; i < wclen; i++)
+	    if (wcptr[i] == '\n')
+	      size += 2;
 	  
 	  if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
 	    {
@@ -246,53 +220,32 @@
 
 	  ucptr = GlobalLock (hdata);
 
-	  switch (method)
+	  p = (wchar_t *) ucptr;
+	  for (i = 0; i < wclen; i++)
 	    {
-	    case SYSTEM_CODEPAGE:
-	      cf = CF_TEXT;
-	      for (i = 0; i < nelements; i++)
-		{
-		  if (data[i] == '\n')
-		    *ucptr++ = '\r';
-		  *ucptr++ = data[i];
-		}
-	      *ucptr++ = '\0';
-	      break;
-
-	    case UNICODE_TEXT:
-	      {
-		wchar_t *p = (wchar_t *) ucptr;
-		cf = CF_UNICODETEXT;
-		for (i = 0; i < wclen; i++)
-		  {
-		    if (wcptr[i] == '\n')
-		      *p++ = '\r';
-		    *p++ = wcptr[i];
-		  }
-		g_free (wcptr);
-	      }
-	      break;
-
-	    default:
-	      g_assert_not_reached ();
+	      if (wcptr[i] == '\n')
+		*p++ = '\r';
+	      *p++ = wcptr[i];
 	    }
+	  g_free (wcptr);
 
 	  GlobalUnlock (hdata);
-	  GDK_NOTE (DND, g_print ("... SetClipboardData(%s,%p)\n",
-				  _gdk_win32_cf_to_string (cf), hdata));
-	  if (ok && !SetClipboardData (cf, hdata))
-	    WIN32_API_FAILED ("SetClipboardData"), ok = FALSE;
+	  GDK_NOTE (DND, g_print ("... SetClipboardData(CF_UNICODETEXT,%p)\n",
+				  hdata));
+	  if (!SetClipboardData (CF_UNICODETEXT, hdata))
+	    WIN32_API_FAILED ("SetClipboardData");
       
 	  if (!CloseClipboard ())
 	    WIN32_API_FAILED ("CloseClipboard");
 	}
       else
         {
-	  GDK_NOTE (DND, g_print ("... delayed rendering\n"));
-	  /* Delayed Rendering. We can't assign hdata to the clipboard
-	   * here as type may be "image/png", "image/jpg", etc.  In
-	   * this case there's a further conversion afterwards.
+	  /* We use delayed rendering for everything else than
+	   * text. We can't assign hdata to the clipboard here as type
+	   * may be "image/png", "image/jpg", etc. In this case
+	   * there's a further conversion afterwards.
 	   */
+	  GDK_NOTE (DND, g_print ("... delayed rendering\n"));
 	  _delayed_rendering_data = NULL;
 	  if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, nelements > 0 ? nelements : 1)))
 	    {
@@ -318,14 +271,16 @@
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  GDK_NOTE (DND,
-	    (prop_name = gdk_atom_name (property),
-	     g_print ("gdk_property_delete: %p %p (%s)\n",
-		      GDK_WINDOW_HWND (window),
-		      property, prop_name),
-	     g_free (prop_name)));
+  GDK_NOTE (DND, {
+      prop_name = gdk_atom_name (property);
+
+      g_print ("gdk_property_delete: %p %s\n",
+	       GDK_WINDOW_HWND (window),
+	       prop_name);
+      g_free (prop_name);
+    });
 
-  if (property == _gdk_selection_property)
+  if (property == _gdk_selection)
     _gdk_selection_property_delete (window);
   else if (property == _wm_transient_for)
     gdk_window_set_transient_for (window, _gdk_root);
@@ -339,37 +294,56 @@
 }
 
 /*
-  for reference copied from gdk/x11/gdkevents-x11.c
+  For reference, from gdk/x11/gdksettings.c:
+
+  "Net/DoubleClickTime\0"     "gtk-double-click-time\0"
+  "Net/DoubleClickDistance\0" "gtk-double-click-distance\0"
+  "Net/DndDragThreshold\0"    "gtk-dnd-drag-threshold\0"
+  "Net/CursorBlink\0"         "gtk-cursor-blink\0"
+  "Net/CursorBlinkTime\0"     "gtk-cursor-blink-time\0"
+  "Net/ThemeName\0"           "gtk-theme-name\0"
+  "Net/IconThemeName\0"       "gtk-icon-theme-name\0"
+  "Gtk/CanChangeAccels\0"     "gtk-can-change-accels\0"
+  "Gtk/ColorPalette\0"        "gtk-color-palette\0"
+  "Gtk/FontName\0"            "gtk-font-name\0"
+  "Gtk/IconSizes\0"           "gtk-icon-sizes\0"
+  "Gtk/KeyThemeName\0"        "gtk-key-theme-name\0"
+  "Gtk/ToolbarStyle\0"        "gtk-toolbar-style\0"
+  "Gtk/ToolbarIconSize\0"     "gtk-toolbar-icon-size\0"
+  "Gtk/IMPreeditStyle\0"      "gtk-im-preedit-style\0"
+  "Gtk/IMStatusStyle\0"       "gtk-im-status-style\0"
+  "Gtk/Modules\0"             "gtk-modules\0"
+  "Gtk/FileChooserBackend\0"  "gtk-file-chooser-backend\0"
+  "Gtk/ButtonImages\0"        "gtk-button-images\0"
+  "Gtk/MenuImages\0"          "gtk-menu-images\0"
+  "Gtk/MenuBarAccel\0"        "gtk-menu-bar-accel\0"
+  "Gtk/CursorThemeName\0"     "gtk-cursor-theme-name\0"
+  "Gtk/CursorThemeSize\0"     "gtk-cursor-theme-size\0"
+  "Gtk/ShowInputMethodMenu\0" "gtk-show-input-method-menu\0"
+  "Gtk/ShowUnicodeMenu\0"     "gtk-show-unicode-menu\0"
+  "Gtk/TimeoutInitial\0"      "gtk-timeout-initial\0"
+  "Gtk/TimeoutRepeat\0"       "gtk-timeout-repeat\0"
+  "Gtk/ColorScheme\0"         "gtk-color-scheme\0"
+  "Gtk/EnableAnimations\0"    "gtk-enable-animations\0"
+  "Xft/Antialias\0"           "gtk-xft-antialias\0"
+  "Xft/Hinting\0"             "gtk-xft-hinting\0"
+  "Xft/HintStyle\0"           "gtk-xft-hintstyle\0"
+  "Xft/RGBA\0"                "gtk-xft-rgba\0"
+  "Xft/DPI\0"                 "gtk-xft-dpi\0"
+  "Net/FallbackIconTheme\0"   "gtk-fallback-icon-theme\0"
+  "Gtk/TouchscreenMode\0"     "gtk-touchscreen-mode\0"
+  "Gtk/EnableAccels\0"        "gtk-enable-accels\0"
+  "Gtk/EnableMnemonics\0"     "gtk-enable-mnemonics\0"
+  "Gtk/ScrolledWindowPlacement\0" "gtk-scrolled-window-placement\0"
+  "Gtk/IMModule\0"            "gtk-im-module\0"
+  "Fontconfig/Timestamp\0"    "gtk-fontconfig-timestamp\0"
+  "Net/SoundThemeName\0"      "gtk-sound-theme-name\0"
+  "Net/EnableInputFeedbackSounds\0" "gtk-enable-input-feedback-sounds\0"
+  "Net/EnableEventSounds\0"  "gtk-enable-event-sounds\0";
 
-  { "Net/DoubleClickTime", "gtk-double-click-time" },
-  { "Net/DoubleClickDistance", "gtk-double-click-distance" },
-  { "Net/DndDragThreshold", "gtk-dnd-drag-threshold" },
-  { "Gtk/CanChangeAccels", "gtk-can-change-accels" },
-  { "Gtk/ColorPalette", "gtk-color-palette" },
-  { "Gtk/FontName", "gtk-font-name" },
-  { "Gtk/IconSizes", "gtk-icon-sizes" },
-  { "Gtk/KeyThemeName", "gtk-key-theme-name" },
-  { "Gtk/ToolbarStyle", "gtk-toolbar-style" },
-  { "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
-  { "Gtk/IMPreeditStyle", "gtk-im-preedit-style" },
-  { "Gtk/IMStatusStyle", "gtk-im-status-style" },
-  { "Gtk/IMModule", "gtk-im-module" },
-  { "Net/CursorBlink", "gtk-cursor-blink" },
-  { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
-  { "Net/ThemeName", "gtk-theme-name" },
-  { "Net/IconThemeName", "gtk-icon-theme-name" },
-  { "Gtk/ButtonImages", "gtk-button-images" },
-  { "Gtk/MenuImages", "gtk-menu-images" },
-  { "Xft/Antialias", "gtk-xft-antialias" },
-  { "Xft/Hinting", "gtk-xft-hinting" },
-  { "Xft/HintStyle", "gtk-xft-hintstyle" },
-  { "Xft/RGBA", "gtk-xft-rgba" },
-  { "Xft/DPI", "gtk-xft-dpi" },
+  More, from various places in gtk sources:
 
-  // more spread in gtk sources
   gtk-entry-select-on-focus
-  gtk-cursor-blink
-  gtk-cursor-blink-time
   gtk-split-cursor
 
 */
@@ -463,6 +437,5 @@
     }
 #endif
 
-  GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) not handled\n", name));
   return FALSE;
 }

Modified: trunk/gdk/win32/gdkselection-win32.c
==============================================================================
--- trunk/gdk/win32/gdkselection-win32.c	(original)
+++ trunk/gdk/win32/gdkselection-win32.c	Fri Jan 30 01:16:47 2009
@@ -35,7 +35,7 @@
 #include "gdkprivate-win32.h"
 
 /* We emulate the GDK_SELECTION window properties of windows (as used
- * in the X11 backend) by using a hash table from GdkWindows to
+ * in the X11 backend) by using a hash table from window handles to
  * GdkSelProp structs.
  */
 
@@ -55,12 +55,89 @@
  */
 static GHashTable *sel_owner_table = NULL;
 
+/* Well-known registered clipboard image formats */
+static UINT cf_png;
+static UINT cf_jfif;
+static UINT cf_gif;
+
+/* GdkAtoms for well-known image formats */
+static GdkAtom *known_pixbuf_formats;
+static int n_known_pixbuf_formats;
+static GdkAtom image_png;
+static GdkAtom image_jpeg;
+static GdkAtom image_bmp;
+static GdkAtom image_gif;
+
+/* GdkAtoms for well-known text formats */
+static GdkAtom text_plain;
+static GdkAtom text_plain_charset_utf_8;
+static GdkAtom text_plain_charset_CP1252;
+
 void
 _gdk_win32_selection_init (void)
 {
+  GSList *pixbuf_formats;
+  GSList *rover;
+
   sel_prop_table = g_hash_table_new (NULL, NULL);
   sel_owner_table = g_hash_table_new (NULL, NULL);
   _format_atom_table = g_hash_table_new (NULL, NULL);
+
+  /* MS Office 2007, at least, offers images in common file formats
+   * using clipboard format names like "PNG" and "JFIF". So we follow
+   * the lead and map the GDK target name "image/png" to the clipboard
+   * format name "PNG" etc.
+   */
+  cf_png = RegisterClipboardFormat ("PNG");
+  cf_jfif = RegisterClipboardFormat ("JFIF");
+  cf_gif = RegisterClipboardFormat ("GIF");
+
+  pixbuf_formats = gdk_pixbuf_get_formats ();
+
+  n_known_pixbuf_formats = 0;
+  for (rover = pixbuf_formats; rover != NULL; rover = rover->next)
+    {
+      gchar **mime_types =
+	gdk_pixbuf_format_get_mime_types ((GdkPixbufFormat *) rover->data);
+
+      gchar **mime_type;
+
+      for (mime_type = mime_types; *mime_type != NULL; mime_type++)
+	n_known_pixbuf_formats++;
+    }
+
+  known_pixbuf_formats = g_new (GdkAtom, n_known_pixbuf_formats);
+
+  n_known_pixbuf_formats = 0;
+  for (rover = pixbuf_formats; rover != NULL; rover = rover->next)
+    {
+      gchar **mime_types =
+	gdk_pixbuf_format_get_mime_types ((GdkPixbufFormat *) rover->data);
+
+      gchar **mime_type;
+
+      for (mime_type = mime_types; *mime_type != NULL; mime_type++)
+	known_pixbuf_formats[n_known_pixbuf_formats++] = gdk_atom_intern (*mime_type, FALSE);
+    }
+
+  g_slist_free (pixbuf_formats);
+  
+  image_png = gdk_atom_intern ("image/png", FALSE);
+  image_jpeg = gdk_atom_intern ("image/jpeg", FALSE);
+  image_bmp = gdk_atom_intern ("image/bmp", FALSE);
+  image_gif = gdk_atom_intern ("image/gif", FALSE);
+
+  text_plain = gdk_atom_intern ("text/plain", FALSE);
+  text_plain_charset_utf_8= gdk_atom_intern ("text/plain;charset=utf-8", FALSE);
+  text_plain_charset_CP1252 = gdk_atom_intern ("text/plain;charset=CP1252", FALSE);
+
+  g_hash_table_replace (_format_atom_table,
+			GINT_TO_POINTER (cf_png),
+			image_png);
+
+  g_hash_table_replace (_format_atom_table,
+			GINT_TO_POINTER (CF_DIB),
+			image_bmp);
 }
 
 /* The specifications for COMPOUND_TEXT and STRING specify that C0 and
@@ -130,42 +207,33 @@
 }
 
 static void
-_gdk_selection_property_store (GdkWindow *owner,
-                               GdkAtom    type,
-                               gint       format,
-                               guchar    *data,
-                               gint       length)
+selection_property_store (GdkWindow *owner,
+			  GdkAtom    type,
+			  gint       format,
+			  guchar    *data,
+			  gint       length)
 {
   GdkSelProp *prop;
-  GSList *prop_list;
 
-  prop = g_new (GdkSelProp, 1);
+  g_return_if_fail (type != GDK_TARGET_STRING);
 
-  if (type == GDK_TARGET_STRING)
-    {
-      /* We know that data is UTF-8 */
-      prop->data = (guchar *) _gdk_utf8_to_string_target_internal ((char*) data, length);
-      g_free (data);
+  prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (owner));
 
-      if (!prop->data)
-	{
-	  g_free (prop);
-
-	  return;
-	}
-      else
-	prop->length = strlen ((char*) prop->data) + 1;
-    }
-  else
+  if (prop != NULL)
     {
-      prop->data = data;
-      prop->length = length;
+      g_free (prop->data);
+      g_free (prop);
+      g_hash_table_remove (sel_prop_table, GDK_WINDOW_HWND (owner));
     }
+
+  prop = g_new (GdkSelProp, 1);
+
+  prop->data = data;
+  prop->length = length;
   prop->format = format;
   prop->type = type;
-  prop_list = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (owner));
-  prop_list = g_slist_append (prop_list, prop);
-  g_hash_table_insert (sel_prop_table, GDK_WINDOW_HWND (owner), prop_list);
+
+  g_hash_table_insert (sel_prop_table, GDK_WINDOW_HWND (owner), prop);
 }
 
 void
@@ -192,6 +260,21 @@
     }
 }
 
+static gchar *
+get_mapped_gdk_atom_name (GdkAtom gdk_target)
+{
+  if (gdk_target == image_png)
+    return g_strdup ("PNG");
+
+  if (gdk_target == image_jpeg)
+    return g_strdup ("JFIF");
+  
+  if (gdk_target == image_gif)
+    return g_strdup ("GIF");
+  
+  return gdk_atom_name (gdk_target);
+}
+
 gboolean
 gdk_selection_owner_set_for_display (GdkDisplay *display,
                                      GdkWindow  *owner,
@@ -205,18 +288,14 @@
   g_return_val_if_fail (display == _gdk_display, FALSE);
   g_return_val_if_fail (selection != GDK_NONE, FALSE);
 
-#ifdef G_ENABLE_DEBUG
-  {
-    gchar *sel_name;
-
-    GDK_NOTE (DND,
-	      (sel_name = gdk_atom_name (selection),
-	       g_print ("gdk_selection_owner_set_for_display: %p %p (%s)\n",
-			(owner ? GDK_WINDOW_HWND (owner) : NULL),
-			selection, sel_name),
-	       g_free (sel_name)));
-  }
-#endif
+  GDK_NOTE (DND, {
+      gchar *sel_name = gdk_atom_name (selection);
+
+      g_print ("gdk_selection_owner_set_for_display: %p %s\n",
+	       (owner ? GDK_WINDOW_HWND (owner) : NULL),
+	       sel_name);
+      g_free (sel_name);
+    });
 
   if (selection != GDK_SELECTION_CLIPBOARD)
     {
@@ -266,7 +345,7 @@
       tmp_event.selection.send_event = FALSE;
       tmp_event.selection.selection = selection;
       tmp_event.selection.target = _utf8_string;
-      tmp_event.selection.property = _gdk_selection_property;
+      tmp_event.selection.property = _gdk_selection;
       tmp_event.selection.requestor = hwnd;
       tmp_event.selection.time = time;
 
@@ -297,18 +376,14 @@
 
   window = gdk_window_lookup ((GdkNativeWindow) g_hash_table_lookup (sel_owner_table, selection));
 
-#ifdef G_ENABLE_DEBUG
-  {
-    gchar *sel_name;
-    
-    GDK_NOTE (DND,
-	      (sel_name = gdk_atom_name (selection),
-	       g_print ("gdk_selection_owner_get: %p (%s) = %p\n",
-			selection, sel_name,
-			(window ? GDK_WINDOW_HWND (window) : NULL)),
-	       g_free (sel_name)));
-  }
-#endif
+  GDK_NOTE (DND, {
+      gchar *sel_name = gdk_atom_name (selection);
+      
+      g_print ("gdk_selection_owner_get: %s = %p\n",
+	       sel_name,
+	       (window ? GDK_WINDOW_HWND (window) : NULL));
+      g_free (sel_name);
+    });
 
   return window;
 }
@@ -341,7 +416,7 @@
 		       guint32    time)
 {
   HGLOBAL hdata;
-  GdkAtom property = _gdk_selection_property;
+  GdkAtom property = _gdk_selection;
 
   g_return_if_fail (selection != GDK_NONE);
   g_return_if_fail (requestor != NULL);
@@ -349,76 +424,119 @@
   if (GDK_WINDOW_DESTROYED (requestor))
     return;
 
-#ifdef G_ENABLE_DEBUG
-  {
-    gchar *sel_name, *tgt_name;
-    
-    GDK_NOTE (DND,
-	      (sel_name = gdk_atom_name (selection),
-	       tgt_name = gdk_atom_name (target),
-	       g_print ("gdk_selection_convert: %p %p (%s) %p (%s)\n",
-			GDK_WINDOW_HWND (requestor),
-			selection, sel_name,
-			target, tgt_name),
-	       g_free (sel_name),
-	       g_free (tgt_name)));
-  }
-#endif
+  GDK_NOTE (DND, {
+      gchar *sel_name = gdk_atom_name (selection);
+      gchar *tgt_name = gdk_atom_name (target);
+      
+      g_print ("gdk_selection_convert: %p %s %s\n",
+	       GDK_WINDOW_HWND (requestor),
+	       sel_name, tgt_name);
+      g_free (sel_name);
+      g_free (tgt_name);
+    });
 
   if (selection == GDK_SELECTION_CLIPBOARD && target == _targets)
     {
-      gint formats_cnt, i, fmt;
-      GdkAtom *data;
+      gint ntargets, fmt;
+      GdkAtom *targets;
+      gboolean has_text = FALSE;
+      gboolean has_png = FALSE;
       gboolean has_bmp = FALSE;
 
-      /* He wants to know what formats are on the clipboard. If there
-       * is some kind of text, tell him so.
-       */
       if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
 	return;
 
-      formats_cnt = CountClipboardFormats ();
-      data = g_new (GdkAtom, formats_cnt + 2);
-      i = 0;
-
-      if (IsClipboardFormatAvailable (CF_UNICODETEXT) ||
-	  IsClipboardFormatAvailable (_cf_utf8_string) ||
-	  IsClipboardFormatAvailable (CF_TEXT))
+      targets = g_new (GdkAtom, CountClipboardFormats ());
+      ntargets = 0;
+
+      for (fmt = 0; 0 != (fmt = EnumClipboardFormats (fmt)); )
 	{
-	  data[i++] = _utf8_string;
+	  if (fmt == cf_png)
+	    {
+	      targets[ntargets++] = image_png;
+	      has_png = TRUE;
+	    }
 	}
-      if (formats_cnt > 0)
-        {
-          /* If there is anything else in the clipboard, enum it all
-           * although we don't offer special conversion services.
-           */
-          for (fmt = 0; 0 != (fmt = EnumClipboardFormats (fmt)); )
-            {
-              gchar sFormat[80];
 
-              if (GetClipboardFormatName (fmt, sFormat, 80) > 0 &&
-		  strcmp (sFormat, "UTF8_STRING"))
-                {
-		  GdkAtom atom;
+      for (fmt = 0; 0 != (fmt = EnumClipboardFormats (fmt)); )
+	{
+	  gchar sFormat[80];
 
-		  if (!has_bmp &&
-		      (!strcmp (sFormat, "image/bmp") ||
-		       !strcmp (sFormat, "image/x-bmp") ||
-		       !strcmp (sFormat, "image/x-MS-bmp")))
-		    has_bmp = TRUE;
-                  atom = gdk_atom_intern (sFormat, FALSE);
-                  data[i++] = atom;
-                }
+	  if (fmt == CF_UNICODETEXT || fmt == CF_TEXT)
+	    {
+	      /* Advertise text to GDK always as UTF8_STRING */
+	      if (!has_text)
+		targets[ntargets++] = _utf8_string;
+	      has_text = TRUE;
+	    }
+	  else if (fmt == cf_png)
+	    {
+	      /* Already handled above */
+	    }
+	  else if (fmt == CF_DIB ||
+		   fmt == CF_DIBV5)
+	    {
+	      /* Don't bother telling that a bitmap is present if there is
+	       * also PNG, which is much more reliable in transferring
+	       * transparency.
+	       */
+	      if (!has_bmp && !has_png)
+		targets[ntargets++] = image_bmp;
+	      has_bmp = TRUE;
+	    }
+	  else if (fmt == cf_jfif)
+	    {
+	      /* Ditto for JPEG */
+	      if (!has_png)
+		targets[ntargets++] = image_jpeg;
+	    }
+	  else if (fmt == cf_gif)
+	    {
+	      /* Ditto for GIF.
+	       */
+	      if (!has_png)
+		targets[ntargets++] = image_gif;
+	    }
+	  else if (GetClipboardFormatName (fmt, sFormat, 80) > 0)
+	    {
+	      if (strcmp (sFormat, "image/bmp") == 0 ||
+		  strcmp (sFormat, "image/x-bmp") == 0 ||
+		  strcmp (sFormat, "image/x-MS-bmp") == 0 ||
+		  strcmp (sFormat, "image/x-icon") == 0 ||
+		  strcmp (sFormat, "image/x-ico") == 0 ||
+		  strcmp (sFormat, "image/x-win-bitmap") == 0)
+		{
+		  /* Ignore these (from older GTK+ versions
+		   * presumably), as the same image in the CF_DIB
+		   * format will also be on the clipboard anyway.
+		   */
+		}
+	      else
+		targets[ntargets++] = gdk_atom_intern (sFormat, FALSE);
             }
         }
-      if (!has_bmp && (IsClipboardFormatAvailable (CF_BITMAP) ||
-		       IsClipboardFormatAvailable (CF_DIB)))
-	data[i++] = _image_bmp;
-
-      if (i > 0)
-	_gdk_selection_property_store (requestor, GDK_SELECTION_TYPE_ATOM,
-				       32, (guchar *) data, i * sizeof (GdkAtom));
-      else             
+
+      GDK_NOTE (DND, {
+	  int i;
+	  
+	  g_print ("... ");
+	  for (i = 0; i < ntargets; i++)
+	    {
+	      gchar *atom_name = gdk_atom_name (targets[i]);
+
+	      g_print ("%s", atom_name);
+	      g_free (atom_name);
+	      if (i < ntargets - 1)
+		g_print (", ");
+	    }
+	  g_print ("\n");
+	});
+
+      if (ntargets > 0)
+	selection_property_store (requestor, GDK_SELECTION_TYPE_ATOM,
+				  32, (guchar *) targets,
+				  ntargets * sizeof (GdkAtom));
+      else
 	property = GDK_NONE;
 
       API_CALL (CloseClipboard, ());
@@ -432,7 +550,6 @@
       if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
 	return;
 
-      /* Try various formats. First the simplest, CF_UNICODETEXT. */
       if ((hdata = GetClipboardData (CF_UNICODETEXT)) != NULL)
 	{
 	  wchar_t *ptr, *wcs, *p, *q;
@@ -465,88 +582,8 @@
 	      g_free (wcs);
 
 	      if (data)
-		_gdk_selection_property_store (requestor, target, 8,
-					       data, strlen (data) + 1);
-	      GlobalUnlock (hdata);
-	    }
-	}
-      else if ((hdata = GetClipboardData (_cf_utf8_string)) != NULL)
-	{
-	  /* UTF8_STRING is a format we store ourselves when necessary */
-	  guchar *ptr;
-	  gint length;
-
-	  if ((ptr = GlobalLock (hdata)) != NULL)
-	    {
-	      length = GlobalSize (hdata);
-	      
-	      GDK_NOTE (DND, g_print ("... UTF8_STRING: %d bytes: %.10s\n",
-				      length, ptr));
-	      
-	      _gdk_selection_property_store (requestor, target, 8,
-					     g_memdup (ptr, length), length);
-	      GlobalUnlock (hdata);
-	    }
-	}
-      else if ((hdata = GetClipboardData (CF_TEXT)) != NULL)
-	{
-	  /* We must always assume the data can contain non-ASCII
-	   * in either the current code page, or if there is CF_LOCALE
-	   * data, in that locale's default code page.
-	   */
-	  HGLOBAL hlcid;
-	  UINT cp = CP_ACP;
-	  wchar_t *wcs, *wcs2, *p, *q;
-	  guchar *ptr, *data;
-	  glong length, wclen, wclen2;
-
-	  if ((ptr = GlobalLock (hdata)) != NULL)
-	    {
-	      length = GlobalSize (hdata);
-	      
-	      GDK_NOTE (DND, g_print ("... CF_TEXT: %ld bytes: %.10s\n",
-				       length, ptr));
-	      
-	      if ((hlcid = GetClipboardData (CF_LOCALE)) != NULL)
-		{
-		  gchar buf[10];
-		  LCID *lcidptr = GlobalLock (hlcid);
-		  if (GetLocaleInfo (*lcidptr, LOCALE_IDEFAULTANSICODEPAGE,
-				     buf, sizeof (buf)))
-		    {
-		      cp = atoi (buf);
-		      GDK_NOTE (DND, g_print ("... CF_LOCALE: %#lx cp:%d\n",
-					      *lcidptr, cp));
-		    }
-		  GlobalUnlock (hlcid);
-		}
-
-	      wcs = g_new (wchar_t, length + 1);
-	      wclen = MultiByteToWideChar (cp, 0, ptr, length,
-					   wcs, length + 1);
-
-	      /* Strip out \r */
-	      wcs2 = g_new (wchar_t, wclen);
-	      p = wcs;
-	      q = wcs2;
-	      wclen2 = 0;
-	      while (p < wcs + wclen)
-		{
-		  if (*p != '\r')
-		    {
-		      *q++ = *p;
-		      wclen2++;
-		    }
-		  p++;
-		}
-	      g_free (wcs);
-
-	      data = g_utf16_to_utf8 (wcs2, wclen2, NULL, &length, NULL);
-	      g_free (wcs2);
-
-	      if (data)
-		_gdk_selection_property_store (requestor, target, 8,
-					       data, length + 1);
+		selection_property_store (requestor, _utf8_string, 8,
+					  data, strlen (data) + 1);
 	      GlobalUnlock (hdata);
 	    }
 	}
@@ -555,80 +592,180 @@
 
       API_CALL (CloseClipboard, ());
     }
-  else if (selection == GDK_SELECTION_CLIPBOARD && target == _image_bmp)
+  else if (selection == GDK_SELECTION_CLIPBOARD && target == image_bmp)
     {
-      guchar *data;
-
       if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
 	return;
-      if ((hdata = GetClipboardData (_cf_image_bmp)) != NULL)
-	{
-	  /* "image/bmp" is the first choice. */
-	  guchar *ptr;
 
-	  if ((ptr = GlobalLock (hdata)) != NULL)
-	    {
-	      gint length = GlobalSize (hdata);
-      
-	      GDK_NOTE (DND, g_print ("...BITMAP (from \"image/bmp\": %d bytes\n",
-				      length));
-      
-	      _gdk_selection_property_store (requestor, target, 8,
-					     g_memdup (ptr, length), length);
-	      GlobalUnlock (hdata);
-	    }
-	}
-      else if ((hdata = GetClipboardData (CF_DIB)) != NULL)
+      if ((hdata = GetClipboardData (CF_DIB)) != NULL)
         {
-	  /* If there's CF_DIB but not "image/bmp", the clipboard
-	   * owner is probably a native Win32 application.
-	   */
-          BITMAPINFOHEADER *ptr;
+          BITMAPINFOHEADER *bi;
 
-          if ((ptr = GlobalLock (hdata)) != NULL)
+          if ((bi = GlobalLock (hdata)) != NULL)
             {
-              BITMAPFILEHEADER *hdr; /* Need to add a file header so gdk-pixbuf can load it */
-	      gint length = GlobalSize (hdata) + sizeof (BITMAPFILEHEADER);
-	      
-	      GDK_NOTE (DND, g_print ("... BITMAP (from CF_DIB): %d bytes\n", length));
+	      /* Need to add a BMP file header so gdk-pixbuf can load
+	       * it.
+	       *
+	       * If the data is from Mozilla Firefox or IE7, and
+	       * starts with an "oldfashioned" BITMAPINFOHEADER,
+	       * i.e. with biSize==40, and biCompression == BI_RGB and
+	       * biBitCount==32, we assume that the "extra" byte in
+	       * each pixel in fact is alpha.
+	       *
+	       * The gdk-pixbuf bmp loader doesn't trust 32-bit BI_RGB
+	       * nitmaps to in fact have alpha, so we have to convince
+	       * it by changint the bitmap header to a version 5
+	       * BI_BITFIELDS one with explicit alpha mask indicated.
+	       *
+	       * The RGB bytes that are in bitmaps on the clipboard
+	       * originating from Firefox or IE7 seem to be
+	       * premultiplied with alpha. The gdk-pixbuf bmp loader
+	       * of course doesn't expect that, so we have to undo the
+	       * premultiplication before feeding the bitmap to the
+	       * bmp loader.
+	       *
+	       * Note that for some reason the bmp loader used to want
+	       * the alpha bytes in its input to actually be
+	       * 255-alpha, but here we assume that this has been
+	       * fixed before this is committed.
+	       */
+              BITMAPFILEHEADER *bf;
+	      gpointer data;
+	      gint data_length = GlobalSize (hdata);
+	      gint new_length;
+	      gboolean make_dibv5 = FALSE;
+
+	      GDK_NOTE (DND, g_print ("... CF_DIB: %d bytes\n", data_length));
+
+	      if (bi->biSize == sizeof (BITMAPINFOHEADER) &&
+		  bi->biPlanes == 1 &&
+		  bi->biBitCount == 32 &&
+		  bi->biCompression == BI_RGB &&
+#if 0
+		  /* Maybe check explicitly for Mozilla or IE7?
+		   *
+		   * If the clipboard format
+		   * application/x-moz-nativeimage is present, that is
+		   * a reliable indicator that the data is offered by
+		   * Mozilla one would think. For IE7,
+		   * UniformResourceLocatorW is presumably not that
+		   * uniqie, so probably need to do some
+		   * GetClipboardOwner(), GetWindowThreadProcessId(),
+		   * OpenProcess(), GetModuleFileNameEx() dance to
+		   * check?
+		   */
+		  (IsClipboardFormatAvailable
+		   (RegisterClipboardFormat ("application/x-moz-nativeimage")) ||
+		   IsClipboardFormatAvailable
+		   (RegisterClipboardFormat ("UniformResourceLocatorW"))) &&
+#endif
+		  TRUE)
+		{
+		  /* We turn the BITMAPINFOHEADER into a
+		   * BITMAPV5HEADER before feeding it to gdk-pixbuf.
+		   */
+		  new_length = (data_length +
+				sizeof (BITMAPFILEHEADER) +
+				(sizeof (BITMAPV5HEADER) - sizeof (BITMAPINFOHEADER)));
+		  make_dibv5 = TRUE;
+		}
+	      else
+		{
+		  new_length = data_length + sizeof (BITMAPFILEHEADER);
+		}
 	      
-              data = g_try_malloc (length);
+              data = g_try_malloc (new_length);
+
               if (data)
                 {
-                  hdr = (BITMAPFILEHEADER *)data;
-                  hdr->bfType = 0x4d42; /* 0x42 = "B" 0x4d = "M" */
-                  /* Compute the size of the entire file. */
-                  hdr->bfSize = (DWORD) (sizeof (BITMAPFILEHEADER)
-                        + ptr->biSize + ptr->biClrUsed
-			* sizeof (RGBQUAD) + ptr->biSizeImage);
-                  hdr->bfReserved1 = 0;
-                  hdr->bfReserved2 = 0;
-                  /* Compute the offset to the array of color indices. */
-                  hdr->bfOffBits = (DWORD) sizeof (BITMAPFILEHEADER)
-                        + ptr->biSize + ptr->biClrUsed * sizeof (RGBQUAD);
-                  /* Copy the data behind it */
-                  memcpy (data + sizeof (BITMAPFILEHEADER), ptr, length - sizeof (BITMAPFILEHEADER));
-	          _gdk_selection_property_store (requestor, target, 8,
-					         data, length);
+                  bf = (BITMAPFILEHEADER *)data;
+                  bf->bfType = 0x4d42; /* "BM" */
+                  bf->bfSize = new_length;
+                  bf->bfReserved1 = 0;
+                  bf->bfReserved2 = 0;
+
+		  if (make_dibv5)
+		    {
+		      BITMAPV5HEADER *bV5 = data + sizeof (BITMAPFILEHEADER);
+		      guchar *p;
+		      int i;
+
+		      bV5->bV5Size = sizeof (BITMAPV5HEADER);
+		      bV5->bV5Width = bi->biWidth;
+		      bV5->bV5Height = bi->biHeight;
+		      bV5->bV5Planes = 1;
+		      bV5->bV5BitCount = 32;
+		      bV5->bV5Compression = BI_BITFIELDS;
+		      bV5->bV5SizeImage = 4 * bV5->bV5Width * ABS (bV5->bV5Height);
+		      bV5->bV5XPelsPerMeter = bi->biXPelsPerMeter;
+		      bV5->bV5YPelsPerMeter = bi->biYPelsPerMeter;
+		      bV5->bV5ClrUsed = 0;
+		      bV5->bV5ClrImportant = 0;
+		      /* Now the added mask fields */
+		      bV5->bV5RedMask   = 0x00ff0000;
+		      bV5->bV5GreenMask = 0x0000ff00;
+		      bV5->bV5BlueMask  = 0x000000ff;
+		      bV5->bV5AlphaMask = 0xff000000;
+		      ((char *) &bV5->bV5CSType)[3] = 's';
+		      ((char *) &bV5->bV5CSType)[2] = 'R';
+		      ((char *) &bV5->bV5CSType)[1] = 'G';
+		      ((char *) &bV5->bV5CSType)[0] = 'B';
+		      /* Ignore colorspace and profile fields */
+		      bV5->bV5Intent = LCS_GM_GRAPHICS;
+		      bV5->bV5Reserved = 0;
+
+		      bf->bfOffBits = (sizeof (BITMAPFILEHEADER) +
+				       bV5->bV5Size);
+
+		      p = ((guchar *) data) + sizeof (BITMAPFILEHEADER) + sizeof (BITMAPV5HEADER);
+		      memcpy (p, ((char *) bi) + bi->biSize,
+			      data_length - sizeof (BITMAPINFOHEADER));
+
+		      for (i = 0; i < bV5->bV5SizeImage/4; i++)
+			{
+			  if (p[3] != 0)
+			    {
+			      gdouble inverse_alpha = 255./p[3];
+			      
+			      p[0] = p[0] * inverse_alpha + 0.5;
+			      p[1] = p[1] * inverse_alpha + 0.5;
+			      p[2] = p[2] * inverse_alpha + 0.5;
+			    }
+
+			  p += 4;
+			}
+		    }
+		  else
+		    {
+		      bf->bfOffBits = (sizeof (BITMAPFILEHEADER) +
+				       bi->biSize +
+				       bi->biClrUsed * sizeof (RGBQUAD));
+
+		      memcpy (data + sizeof (BITMAPFILEHEADER),
+			      bi,
+			      data_length);
+		    }
+
+	          selection_property_store (requestor, image_bmp, 8,
+					    data, new_length);
                 }
 	      GlobalUnlock (hdata);
             }
-
       }
 
       API_CALL (CloseClipboard, ());
     }
   else if (selection == GDK_SELECTION_CLIPBOARD)
     {
-      char *target_name;
+      gchar *mapped_target_name;
       UINT fmt = 0;
 
       if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
 	return;
 
-      target_name = gdk_atom_name (target);
+      mapped_target_name = get_mapped_gdk_atom_name (target);
 
-      /* Check if it's available. In fact, we can simply call
+      /* Check if it's available. We could simply call
        * GetClipboardData (RegisterClipboardFormat (targetname)), but
        * the global custom format ID space is limited,
        * (0xC000~0xFFFF), and we better not waste an format ID if we
@@ -639,7 +776,7 @@
           char sFormat[80];
 
           if (GetClipboardFormatName (fmt, sFormat, 80) > 0 && 
-              strcmp (sFormat, target_name) == 0)
+              strcmp (sFormat, mapped_target_name) == 0)
             {
               if ((hdata = GetClipboardData (fmt)) != NULL)
 	        {
@@ -651,17 +788,17 @@
                     {
                       length = GlobalSize (hdata);
 	      
-                      GDK_NOTE (DND, g_print ("... %s: %d bytes\n", target_name, length));
+                      GDK_NOTE (DND, g_print ("... %s: %d bytes\n", mapped_target_name, length));
 	      
-                      _gdk_selection_property_store (requestor, target, 8,
-					             g_memdup (ptr, length), length);
+                      selection_property_store (requestor, target, 8,
+						g_memdup (ptr, length), length);
 	              GlobalUnlock (hdata);
                       break;
                     }
                 }
             }
         }
-      g_free (target_name);
+      g_free (mapped_target_name);
       API_CALL (CloseClipboard, ());
     }
   else if (selection == _gdk_win32_dropfiles)
@@ -672,7 +809,7 @@
        */
       if (dropfiles_prop != NULL)
 	{
-	  _gdk_selection_property_store
+	  selection_property_store
 	    (requestor, selection, dropfiles_prop->format,
 	     dropfiles_prop->data, dropfiles_prop->length);
 	  g_free (dropfiles_prop);
@@ -682,9 +819,9 @@
   else
     property = GDK_NONE;
 
-  /* Generate a selection notify message so that we actually fetch
-   * the data (if property == _gdk_selection_property) or indicating failure
-   * (if property == GDK_NONE).
+  /* Generate a selection notify message so that we actually fetch the
+   * data (if property == _gdk_selection) or indicating failure (if
+   * property == GDK_NONE).
    */
   generate_selection_notify (requestor, selection, target, property, time);
 }
@@ -696,7 +833,6 @@
 			    gint       *ret_format)
 {
   GdkSelProp *prop;
-  GSList *prop_list;
 
   g_return_val_if_fail (requestor != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
@@ -704,15 +840,16 @@
   if (GDK_WINDOW_DESTROYED (requestor))
     return 0;
   
-  GDK_NOTE (DND, g_print ("gdk_selection_property_get: %p\n",
+  GDK_NOTE (DND, g_print ("gdk_selection_property_get: %p",
 			   GDK_WINDOW_HWND (requestor)));
 
-  prop_list = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (requestor));
-  prop = prop_list ? (GdkSelProp *) prop_list->data : NULL;
+  prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (requestor));
 
   if (prop == NULL)
     {
+      GDK_NOTE (DND, g_print (" (nothing)\n"));
       *data = NULL;
+
       return 0;
     }
 
@@ -721,6 +858,13 @@
   if (prop->length > 0)
     memmove (*data, prop->data, prop->length);
 
+  GDK_NOTE (DND, {
+      gchar *type_name = gdk_atom_name (prop->type);
+
+      g_print (" %s format:%d length:%d\n", type_name, prop->format, prop->length);
+      g_free (type_name);
+    });
+
   if (ret_type)
     *ret_type = prop->type;
 
@@ -734,19 +878,19 @@
 _gdk_selection_property_delete (GdkWindow *window)
 {
   GdkSelProp *prop;
-  GSList *prop_list;
   
-  GDK_NOTE (DND, g_print ("_gdk_selection_property_delete: %p\n",
+  GDK_NOTE (DND, g_print ("_gdk_selection_property_delete: %p (no-op)\n",
 			   GDK_WINDOW_HWND (window)));
 
-  prop_list = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (window));
-  if (prop_list && (prop = (GdkSelProp *) prop_list->data) != NULL)
+#if 0
+  prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (window));
+  if (prop != NULL)
     {
       g_free (prop->data);
-      prop_list = g_slist_remove (prop_list, prop);
       g_free (prop);
-      g_hash_table_insert (sel_prop_table, GDK_WINDOW_HWND (window), prop_list);
+      g_hash_table_remove (sel_prop_table, GDK_WINDOW_HWND (window));
     }
+#endif
 }
 
 void
@@ -759,24 +903,17 @@
 {
   g_return_if_fail (display == _gdk_display);
 
-#ifdef G_ENABLE_DEBUG
-  {
-    gchar *sel_name, *tgt_name, *prop_name;
-
-    GDK_NOTE (DND,
-	      (sel_name = gdk_atom_name (selection),
-	       tgt_name = gdk_atom_name (target),
-	       prop_name = gdk_atom_name (property),
-	       g_print ("gdk_selection_send_notify_for_display: %p %p (%s) %p (%s) %p (%s)\n",
-			requestor,
-			selection, sel_name,
-			target, tgt_name,
-			property, prop_name),
-	       g_free (sel_name),
-	       g_free (tgt_name),
-	       g_free (prop_name)));
-  }
-#endif
+  GDK_NOTE (DND, {
+      gchar *sel_name = gdk_atom_name (selection);
+      gchar *tgt_name = gdk_atom_name (target);
+      gchar *prop_name = gdk_atom_name (property);
+      
+      g_print ("gdk_selection_send_notify_for_display: %p %s %s %s (no-op)\n",
+	       requestor, sel_name, tgt_name, prop_name);
+      g_free (sel_name);
+      g_free (tgt_name);
+      g_free (prop_name);
+    });
 }
 
 /* It's hard to say whether implementing this actually is of any use
@@ -797,16 +934,13 @@
 
   g_return_val_if_fail (display == _gdk_display, 0);
 
-#ifdef G_ENABLE_DEBUG
-  {
-    gchar *enc_name;
-
-    GDK_NOTE (DND, (enc_name = gdk_atom_name (encoding),
-		    g_print ("gdk_text_property_to_text_list_for_display: %s %d %.20s %d\n",
-			     enc_name, format, text, length),
-		    g_free (enc_name)));
-  }
-#endif
+  GDK_NOTE (DND, {
+      gchar *enc_name = gdk_atom_name (encoding);
+      
+      g_print ("gdk_text_property_to_text_list_for_display: %s %d %.20s %d\n",
+	       enc_name, format, text, length);
+      g_free (enc_name);
+    });
     
   if (!list)
     return 0;
@@ -1022,6 +1156,13 @@
   g_return_if_fail (ctext == NULL);
 }
 
+/* This function is called from gtk_selection_add_target() and
+ * gtk_selection_add_targets() in gtkselection.c. It is this function
+ * that takes care of setting those clipboard formats for which we use
+ * delayed rendering. Formats copied directly to the clipboard are
+ * handled in gdk_property_change() in gdkproperty-win32.c.
+ */
+
 void
 gdk_win32_selection_add_targets (GdkWindow  *owner,
 				 GdkAtom     selection,
@@ -1029,14 +1170,10 @@
 				 GdkAtom    *targets)
 {
   HWND hwnd = NULL;
-  guint formatid;
+  gboolean has_image = FALSE;
   gint i;
-  GSList *convertable_formats, *format;
-  gboolean has_set_dib = FALSE, has_real_dib = FALSE;
 
-#ifdef G_ENABLE_DEBUG
-  if (_gdk_debug_flags & GDK_DEBUG_DND)
-    {
+  GDK_NOTE (DND, {
       gchar *sel_name = gdk_atom_name (selection);
       
       g_print ("gdk_win32_selection_add_targets: %p: %s: ",
@@ -1048,12 +1185,13 @@
 	{
 	  gchar *tgt_name = gdk_atom_name (targets[i]);
 
-	  g_print ("%s ", tgt_name);
+	  g_print ("%s", tgt_name);
 	  g_free (tgt_name);
+	  if (i < n_targets - 1)
+	    g_print (", ");
 	}
       g_print ("\n");
-    }
-#endif
+    });
 
   if (selection != GDK_SELECTION_CLIPBOARD)
     return;
@@ -1068,80 +1206,77 @@
   if (!API_CALL (OpenClipboard, (hwnd)))
     return;
 
-  convertable_formats = gdk_pixbuf_get_formats ();
-  for (i = 0; i < n_targets; ++i)
+  /* We have a very simple strategy: If some kind of pixmap image
+   * format is being added, actually advertise just PNG and DIB. PNG
+   * is our preferred format because it can losslessly represent any
+   * image that gdk-pixbuf formats in general can, even with alpha,
+   * unambiguously. CF_DIB is also advertised because of the general
+   * support for it in Windows software, but note that alpha won't be
+   * handled.
+   */
+  for (i = 0; !has_image && i < n_targets; ++i)
     {
+      UINT cf;
       gchar *target_name;
+      int j;
+      
+      for (j = 0; j < n_known_pixbuf_formats; j++)
+	if (targets[i] == known_pixbuf_formats[j])
+	  {
+	    if (!has_image)
+	      {
+		GDK_NOTE (DND, g_print ("... SetClipboardData(PNG,NULL)\n"));
+		SetClipboardData (cf_png, NULL);
+
+		GDK_NOTE (DND, g_print ("... SetClipboardData(CF_DIB,NULL)\n"));
+		SetClipboardData (CF_DIB, NULL);
+
+		has_image = TRUE;
+	      }
+	    break;
+	  }
+      
+      /* If it is one of the pixmap formats, already handled or not
+       * needed.
+       */
+      if (j < n_known_pixbuf_formats)
+	continue;
 
-      if (targets[i] == _utf8_string ||
+      /* We don't bother registering and advertising clipboard formats
+       * that are X11 specific or no non-GTK+ apps will have ever
+       * heard of, and when there are equivalent clipboard formats
+       * that are commonly used.
+       */
+      if (targets[i] == _save_targets ||
+	  targets[i] == _utf8_string ||
 	  targets[i] == GDK_TARGET_STRING ||
-	  targets[i] == _text ||
 	  targets[i] == _compound_text ||
-	  targets[i] == _save_targets)
+	  targets[i] == _text ||
+	  targets[i] == text_plain_charset_utf_8 ||
+	  targets[i] == text_plain_charset_CP1252 ||
+	  targets[i] == text_plain)
 	continue;
 
       target_name = gdk_atom_name (targets[i]);
-      if (!(formatid = RegisterClipboardFormat (target_name)))
-	{
-	  WIN32_API_FAILED ("RegisterClipboardFormat");
-	  API_CALL (CloseClipboard, ());
-	  g_free (target_name);
-	  return;
-	}
-      g_hash_table_replace (_format_atom_table, GINT_TO_POINTER (formatid), targets[i]);
-
-      GDK_NOTE (DND, g_print ("... SetClipboardData(%s,NULL)\n",
-			      _gdk_win32_cf_to_string (formatid)));
-      SetClipboardData (formatid, NULL);
 
-      /* We should replace the previous image format associated with
-       * CF_DIB with "image/bmp" if we find "image/bmp", "image/x-bmp"
-       * or "image/x-MS-bmp" is available.
-       */
-      if (!has_real_dib &&
-	  (!strcmp (target_name, "image/bmp") ||
-	   !strcmp (target_name, "image/x-bmp") ||
-	   !strcmp (target_name, "image/x-MS-bmp")))
+      if (g_str_has_prefix (target_name, "text/plain;charset="))
 	{
-	  g_hash_table_replace (_format_atom_table,
-				GINT_TO_POINTER (CF_DIB),
-				targets[i]);
-	  if (!has_set_dib)
-	    {
-	      GDK_NOTE (DND, g_print ("... SetClipboardData(CF_DIB,NULL)\n"));
-	      SetClipboardData (CF_DIB, NULL);
-	      has_set_dib = TRUE;
-	    }
-	  has_real_dib = TRUE;
 	  g_free (target_name);
 	  continue;
 	}
 
-      for (format = convertable_formats; !has_set_dib && format; format = format->next)
-	{
-	  gchar **mime_types =
-	    gdk_pixbuf_format_get_mime_types ((GdkPixbufFormat *) format->data);
-	  gchar **mime_type;
+      cf = RegisterClipboardFormat (target_name);
+
+      g_hash_table_replace (_format_atom_table,
+			    GINT_TO_POINTER (cf),
+			    targets[i]);
+      
+      GDK_NOTE (DND, g_print ("... SetClipboardData(%s,NULL)\n",
+			      _gdk_win32_cf_to_string (cf)));
+      SetClipboardData (cf, NULL);
 
-	  for (mime_type = mime_types; *mime_type; ++mime_type)
-	    {
-	      if (!strcmp (target_name, *mime_type))
-	        {
-		  g_hash_table_replace (_format_atom_table,
-					GINT_TO_POINTER (CF_DIB),
-					targets[i]);
-		  GDK_NOTE (DND, g_print ("... SetClipboardData(CF_DIB,NULL)\n"));
-		  SetClipboardData (CF_DIB, NULL);
-		  has_set_dib = TRUE;
-		  break;
-		}
-	    }
-	  g_strfreev(mime_types);
-	}
       g_free (target_name);
     }
-  g_slist_free (convertable_formats);
-
   API_CALL (CloseClipboard, ());
 }
 
@@ -1153,84 +1288,33 @@
 _gdk_win32_selection_convert_to_dib (HGLOBAL  hdata,
 				     GdkAtom  target)
 {
-  GdkPixbufLoader *loader;
-  GdkPixbuf *pixbuf;
-  gchar *target_name;
-  guchar *ptr;
-  gchar *bmp_buf;
-  gsize size;
-  gboolean ok;
-
-  if (!(target_name = gdk_atom_name (target)))
-    {
-      GlobalFree (hdata);
-      return NULL;
-    }
-
-  if (!strcmp (target_name, "image/bmp") ||
-      !strcmp (target_name, "image/x-bmp") ||
-      !strcmp (target_name, "image/x-MS-bmp"))
+  GDK_NOTE (DND, {
+      gchar *target_name = gdk_atom_name (target);
+
+      g_print ("_gdk_win32_selection_convert_to_dib: %p %s\n",
+	       hdata, target_name);
+      g_free (target_name);
+    });
+
+  if (target == image_bmp)
     {
       /* No conversion is needed, just strip the BITMAPFILEHEADER */
       HGLOBAL hdatanew;
+      SIZE_T size = GlobalSize (hdata) - sizeof (BITMAPFILEHEADER);
+      guchar *ptr = GlobalLock (hdata);
 
-      g_free (target_name);
-      size = GlobalSize (hdata) - sizeof (BITMAPFILEHEADER);
-      ptr = GlobalLock (hdata);
       memmove (ptr, ptr + sizeof (BITMAPFILEHEADER), size);
       GlobalUnlock (hdata);
-      if (!(hdatanew = GlobalReAlloc (hdata, size, 0)))
+
+      if ((hdatanew = GlobalReAlloc (hdata, size, GMEM_MOVEABLE)) == NULL)
 	{
 	  WIN32_API_FAILED ("GlobalReAlloc");
-	  GlobalFree (hdata); /* the old hdata is not freed if error */
+	  GlobalFree (hdata); /* The old hdata is not freed if error */
 	}
       return hdatanew;
     }
 
-  /* We actually provide image formats -other than- "image/bmp" etc
-   * and the requestor is either a native Win32 application or a GTK+
-   * client that requested "image/bmp".
-   */
-  if (!(loader = gdk_pixbuf_loader_new_with_mime_type (target_name, NULL)))
-    {
-      GlobalFree (hdata);
-      g_free (target_name);
-      return NULL;
-    }
-  g_free (target_name);
-
-  ptr = GlobalLock (hdata);
-  ok = gdk_pixbuf_loader_write (loader, ptr, GlobalSize (hdata) - 1, NULL) &&
-       gdk_pixbuf_loader_close (loader, NULL);
-
-  GlobalUnlock (hdata);
-  GlobalFree (hdata);
-  hdata = NULL;
-
-  if (ok && (pixbuf = gdk_pixbuf_loader_get_pixbuf (loader)) != NULL)
-    g_object_ref (pixbuf);
-
-  g_object_unref (loader);
-
-  if (ok && gdk_pixbuf_save_to_buffer (pixbuf, &bmp_buf, &size, "bmp", NULL, NULL))
-    {
-      size -= sizeof (BITMAPFILEHEADER);
-      if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
-	{
-	  WIN32_API_FAILED ("GlobalAlloc");
-	  ok = FALSE;
-	}
-
-      if (ok)
-	{
-	  ptr = GlobalLock (hdata);
-	  memcpy (ptr, bmp_buf + sizeof (BITMAPFILEHEADER), size);
-	  GlobalUnlock (hdata);
-	}
-
-      g_free (bmp_buf);
-      g_object_unref (pixbuf);
-    }
+  g_warning ("Should not happen: We provide some image format but not CF_DIB and CF_DIB is requested.");
 
-  return hdata;
+  return NULL;
 }



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