]> Pileus Git - ~andy/gtk/commitdiff
New debugging function, to log a clipboard format name symbolically.
authorTor Lillqvist <tml@novell.com>
Mon, 4 Apr 2005 00:12:26 +0000 (00:12 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Mon, 4 Apr 2005 00:12:26 +0000 (00:12 +0000)
2005-04-04  Tor Lillqvist  <tml@novell.com>

* gdk/win32/gdkmain.c (_gdk_win32_cf_to_string): New debugging
function, to log a clipboard format name symbolically.
(_gdk_win32_data_to_string): Also new, to log random data bytes.

Implement delayed rendering on Win32, specifically for transfering
images through the clipboard from GTK+ apps to other
apps (#168173, implementation by Ivan Wong):

* gdk/win32/gdkevents-win32.c (gdk_event_translate):
Handle WM_RENDERFORMAT.

* gdk/win32/gdkprivate-win32.h
* gdk/win32/gdkglobals-win32.c: Add _format_atom_table,
_delayed_rendering_data and _image_bmp.

* gdk/win32/gdkmain-win32.c: Initialize _image_bmp.

* gdk/win32/gdkproperty-win32.c (gdk_property_change):
Accept formats other than GDK_TARGET_STRING or _utf8_string, and
assume they are handled through delayed rendering.

* gdk/win32/gdkselection-win32.c (gdk_selection_convert):
Return all available formats (including those registered by GTK+
apps) on request_targets.
(gdk_selection_property_get): We should append a zero byte like
X11 does.
(gdk_win32_selection_add_targets): New function, for
gtkselection's use. Win32 requires that the clipboard owner
registers all valid formats even if the owner wants delayed
rendering.
(_gdk_win32_selection_convert_to_dib): New function. Convert
images to DIB using gdk-pixbuf.

* gdk/win32/gdkwin32.h: Declare gdk_win32_selection_add_targets().

* gtk/gtkselection.c (gtk_selection_add_target,
gtk_selection_add_targets): Call gdk_win32_selection_add_targets()
to register target formats.

* gdk/gdk.symbols: Add gdk_win32_selection_add_targets().

13 files changed:
ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-8
gdk/gdk.symbols
gdk/win32/gdkdisplay-win32.c
gdk/win32/gdkevents-win32.c
gdk/win32/gdkglobals-win32.c
gdk/win32/gdkmain-win32.c
gdk/win32/gdkprivate-win32.h
gdk/win32/gdkproperty-win32.c
gdk/win32/gdkselection-win32.c
gdk/win32/gdkwin32.h
gtk/gtkselection.c

index 7286577da05f5b408bbe99d0cacdae7b31928a99..82c25cf30da3f9cdbb46aa4b8bb36e56e4a1cdbb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,46 @@
+2005-04-04  Tor Lillqvist  <tml@novell.com>
+
+       * gdk/win32/gdkmain.c (_gdk_win32_cf_to_string): New debugging
+       function, to log a clipboard format name symbolically.
+       (_gdk_win32_data_to_string): Also new, to log random data bytes.
+
+       Implement delayed rendering on Win32, specifically for transfering
+       images through the clipboard from GTK+ apps to other
+       apps (#168173, implementation by Ivan Wong):
+
+       * gdk/win32/gdkevents-win32.c (gdk_event_translate): 
+       Handle WM_RENDERFORMAT.
+
+       * gdk/win32/gdkprivate-win32.h
+       * gdk/win32/gdkglobals-win32.c: Add _format_atom_table,
+       _delayed_rendering_data and _image_bmp.
+
+       * gdk/win32/gdkmain-win32.c: Initialize _image_bmp.
+
+       * gdk/win32/gdkproperty-win32.c (gdk_property_change):
+       Accept formats other than GDK_TARGET_STRING or _utf8_string, and
+       assume they are handled through delayed rendering.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_convert):
+       Return all available formats (including those registered by GTK+
+       apps) on request_targets.
+       (gdk_selection_property_get): We should append a zero byte like
+       X11 does.
+       (gdk_win32_selection_add_targets): New function, for
+       gtkselection's use. Win32 requires that the clipboard owner
+       registers all valid formats even if the owner wants delayed
+       rendering.
+       (_gdk_win32_selection_convert_to_dib): New function. Convert
+       images to DIB using gdk-pixbuf.
+
+       * gdk/win32/gdkwin32.h: Declare gdk_win32_selection_add_targets().
+
+       * gtk/gtkselection.c (gtk_selection_add_target,
+       gtk_selection_add_targets): Call gdk_win32_selection_add_targets()
+       to register target formats.
+
+       * gdk/gdk.symbols: Add gdk_win32_selection_add_targets().
+
 2005-04-03  Hans Breuer  <hans@breuer.org>
 
        [merged from gtk-2-6 branch]
index 7286577da05f5b408bbe99d0cacdae7b31928a99..82c25cf30da3f9cdbb46aa4b8bb36e56e4a1cdbb 100644 (file)
@@ -1,3 +1,46 @@
+2005-04-04  Tor Lillqvist  <tml@novell.com>
+
+       * gdk/win32/gdkmain.c (_gdk_win32_cf_to_string): New debugging
+       function, to log a clipboard format name symbolically.
+       (_gdk_win32_data_to_string): Also new, to log random data bytes.
+
+       Implement delayed rendering on Win32, specifically for transfering
+       images through the clipboard from GTK+ apps to other
+       apps (#168173, implementation by Ivan Wong):
+
+       * gdk/win32/gdkevents-win32.c (gdk_event_translate): 
+       Handle WM_RENDERFORMAT.
+
+       * gdk/win32/gdkprivate-win32.h
+       * gdk/win32/gdkglobals-win32.c: Add _format_atom_table,
+       _delayed_rendering_data and _image_bmp.
+
+       * gdk/win32/gdkmain-win32.c: Initialize _image_bmp.
+
+       * gdk/win32/gdkproperty-win32.c (gdk_property_change):
+       Accept formats other than GDK_TARGET_STRING or _utf8_string, and
+       assume they are handled through delayed rendering.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_convert):
+       Return all available formats (including those registered by GTK+
+       apps) on request_targets.
+       (gdk_selection_property_get): We should append a zero byte like
+       X11 does.
+       (gdk_win32_selection_add_targets): New function, for
+       gtkselection's use. Win32 requires that the clipboard owner
+       registers all valid formats even if the owner wants delayed
+       rendering.
+       (_gdk_win32_selection_convert_to_dib): New function. Convert
+       images to DIB using gdk-pixbuf.
+
+       * gdk/win32/gdkwin32.h: Declare gdk_win32_selection_add_targets().
+
+       * gtk/gtkselection.c (gtk_selection_add_target,
+       gtk_selection_add_targets): Call gdk_win32_selection_add_targets()
+       to register target formats.
+
+       * gdk/gdk.symbols: Add gdk_win32_selection_add_targets().
+
 2005-04-03  Hans Breuer  <hans@breuer.org>
 
        [merged from gtk-2-6 branch]
index 7286577da05f5b408bbe99d0cacdae7b31928a99..82c25cf30da3f9cdbb46aa4b8bb36e56e4a1cdbb 100644 (file)
@@ -1,3 +1,46 @@
+2005-04-04  Tor Lillqvist  <tml@novell.com>
+
+       * gdk/win32/gdkmain.c (_gdk_win32_cf_to_string): New debugging
+       function, to log a clipboard format name symbolically.
+       (_gdk_win32_data_to_string): Also new, to log random data bytes.
+
+       Implement delayed rendering on Win32, specifically for transfering
+       images through the clipboard from GTK+ apps to other
+       apps (#168173, implementation by Ivan Wong):
+
+       * gdk/win32/gdkevents-win32.c (gdk_event_translate): 
+       Handle WM_RENDERFORMAT.
+
+       * gdk/win32/gdkprivate-win32.h
+       * gdk/win32/gdkglobals-win32.c: Add _format_atom_table,
+       _delayed_rendering_data and _image_bmp.
+
+       * gdk/win32/gdkmain-win32.c: Initialize _image_bmp.
+
+       * gdk/win32/gdkproperty-win32.c (gdk_property_change):
+       Accept formats other than GDK_TARGET_STRING or _utf8_string, and
+       assume they are handled through delayed rendering.
+
+       * gdk/win32/gdkselection-win32.c (gdk_selection_convert):
+       Return all available formats (including those registered by GTK+
+       apps) on request_targets.
+       (gdk_selection_property_get): We should append a zero byte like
+       X11 does.
+       (gdk_win32_selection_add_targets): New function, for
+       gtkselection's use. Win32 requires that the clipboard owner
+       registers all valid formats even if the owner wants delayed
+       rendering.
+       (_gdk_win32_selection_convert_to_dib): New function. Convert
+       images to DIB using gdk-pixbuf.
+
+       * gdk/win32/gdkwin32.h: Declare gdk_win32_selection_add_targets().
+
+       * gtk/gtkselection.c (gtk_selection_add_target,
+       gtk_selection_add_targets): Call gdk_win32_selection_add_targets()
+       to register target formats.
+
+       * gdk/gdk.symbols: Add gdk_win32_selection_add_targets().
+
 2005-04-03  Hans Breuer  <hans@breuer.org>
 
        [merged from gtk-2-6 branch]
index 07b14120426d371ca1cb6ad592ed83239be931c6..34a9f7e027559fea3c6fad44016e559eee31e246 100644 (file)
@@ -1047,6 +1047,12 @@ gdk_win32_hdc_get
 gdk_win32_hdc_release
 #endif
 #endif
+
+#if IN_HEADER(__GDK_WIN32_H__)
+#if IN_FILE(__GDK_SELECTION_WIN32_C__)
+gdk_win32_selection_add_targets
+#endif
+#endif
 #endif
 
 #ifdef GDK_WINDOWING_X11
index eca6de6a73f21d866cab68948d8cc7302e106c53..fe08e4584149f316495fd7372964f7b41bc2f34b 100644 (file)
@@ -375,9 +375,7 @@ _win32_on_clipboard_change (HWND   hwnd,
            g_print ("WM_DRAWCLIPBOARD: owner:%p formats: ", hwndOwner);
            for (; 0 != (nFormat = EnumClipboardFormats (nFormat));)
              {
-               char sFormat[80];
-               if (GetClipboardFormatName (nFormat, sFormat, G_N_ELEMENTS (sFormat)) > 0)
-                 g_print ("%s ", sFormat);
+               g_print ("%s ", _gdk_win32_cf_to_string (nFormat));
              }
            g_print ("\n");
            CloseClipboard ();
index 5bf455c122669d66a2497d3675f28196305a712c..222b457c8d1dfd8128ae99695ead6b4a83730ebc 100644 (file)
@@ -2178,6 +2178,7 @@ gdk_event_translate (GdkDisplay *display,
 
   static gint update_colors_counter = 0;
   gint button;
+  GdkAtom target;
 
   gchar buf[256];
   gboolean return_val = FALSE;
@@ -3362,7 +3363,62 @@ gdk_event_translate (GdkDisplay *display,
       else
        return_val = TRUE;
       break;
+
+    case WM_RENDERFORMAT:
+      GDK_NOTE (EVENTS, g_print (" %s", _gdk_win32_cf_to_string (msg->wParam)));
+
+      if (!(target = g_hash_table_lookup (_format_atom_table, GINT_TO_POINTER (msg->wParam))))
+       {
+         GDK_NOTE (EVENTS, g_print (" (target not found)"));
+         return_val = TRUE;
+         break;
+       }
+
+      /* We need to render to clipboard immediately, don't call
+       * append_event()
+       */
+      if (_gdk_event_func)
+       {
+         event = gdk_event_new (GDK_SELECTION_REQUEST);
+         event->selection.window = window;
+         event->selection.send_event = FALSE;
+         event->selection.selection = GDK_SELECTION_CLIPBOARD;
+         event->selection.target = target;
+         event->selection.property = _gdk_selection_property;
+         event->selection.requestor = (guint32) msg->hwnd;
+         event->selection.time = msg->time;
+
+         fixup_event (event);
+         GDK_NOTE (EVENTS, g_print (" (calling gdk_event_func)"));
+         GDK_NOTE (EVENTS, print_event (event));
+         (*_gdk_event_func) (event, _gdk_event_data);
+         gdk_event_free (event);
+
+         /* Now the clipboard owner should have rendered */
+         if (!_delayed_rendering_data)
+           GDK_NOTE (EVENTS, g_print (" (no _delayed_rendering_data?)"));
+         else
+           {
+             if (msg->wParam == CF_DIB)
+               {
+                 _delayed_rendering_data =
+                   _gdk_win32_selection_convert_to_dib (_delayed_rendering_data,
+                                                        target);
+                 if (!_delayed_rendering_data)
+                   {
+                     g_warning ("Cannot convert to DIB from delayed rendered image");
+                     break;
+                   }
+               }
+             /* The requestor is holding the clipboard, no
+              * OpenClipboard() is required/possible
+              */
+             API_CALL (SetClipboardData, (msg->wParam, _delayed_rendering_data));
+             _delayed_rendering_data = NULL;
+           }
+       }
+      break;
+
 #ifdef HAVE_WINTAB
     case WM_ACTIVATE:
       /* Bring any tablet contexts to the top of the overlap order when
index 26fb203834dee170f327ff1fe55f3530114702ef..a178ccbf25af0eac9f394bcab0515bfb864c8054 100644 (file)
@@ -36,7 +36,7 @@ GdkWindow      *_gdk_root = NULL;
 gint             _gdk_num_monitors;
 GdkRectangle     *_gdk_monitors = NULL;
 
-gint            _gdk_offset_x, _gdk_offset_y;
+gint             _gdk_offset_x, _gdk_offset_y;
 
 HDC              _gdk_display_hdc;
 HINSTANCE        _gdk_dll_hinstance;
@@ -50,9 +50,11 @@ WORD                   _cf_rtf;
 WORD             _cf_utf8_string;
 
 GdkAtom           _utf8_string;
-GdkAtom                  _text_uri_list;
 GdkAtom                  _targets;
 
+GdkAtom                  _text_uri_list;
+GdkAtom                  _image_bmp;
+
 GdkAtom                  _local_dnd;
 GdkAtom                  _gdk_win32_dropfiles;
 GdkAtom                  _gdk_ole2_dnd;
@@ -66,3 +68,6 @@ gint            _gdk_max_colors = 0;
 
 gboolean         _sizemove_in_progress = FALSE;
 gboolean         _ignore_destroy_clipboard = FALSE;
+
+HGLOBAL           _delayed_rendering_data = NULL;
+GHashTable       *_format_atom_table = NULL;
index d12e56feec9529246b5f130fc9a0d612f7c02d43..2584a2ada6aac57171879e9f507b14079f3ba0a5 100644 (file)
@@ -112,9 +112,11 @@ _gdk_windowing_init (void)
   _cf_utf8_string = RegisterClipboardFormat ("UTF8_STRING");
 
   _utf8_string = gdk_atom_intern ("UTF8_STRING", FALSE);
-  _text_uri_list = gdk_atom_intern ("text/uri-list", FALSE);
   _targets = gdk_atom_intern ("TARGETS", 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);
   _gdk_ole2_dnd = gdk_atom_intern ("OLE2_DND", FALSE);
@@ -250,7 +252,7 @@ gdk_notify_startup_complete (void)
  */
 static gchar *
 static_printf (const gchar *format,
-                        ...)
+              ...)
 {
   static gchar buf[10000];
   gchar *msg;
@@ -922,6 +924,71 @@ _gdk_win32_key_to_string (LONG lParam)
   return static_printf ("unk-%#lx", lParam);
 }
       
+gchar *
+_gdk_win32_cf_to_string (UINT format)
+{
+  char buf[100];
+
+  switch (format)
+    {
+#define CASE(x) case CF_##x: return #x
+      CASE (BITMAP);
+      CASE (DIB);
+#ifdef CF_DIBV5
+      CASE (DIBV5);
+#endif
+      CASE (DIF);
+      CASE (DSPBITMAP);
+      CASE (DSPENHMETAFILE);
+      CASE (DSPMETAFILEPICT);
+      CASE (DSPTEXT);
+      CASE (ENHMETAFILE);
+      CASE (HDROP);
+      CASE (LOCALE);
+      CASE (METAFILEPICT);
+      CASE (OEMTEXT);
+      CASE (OWNERDISPLAY);
+      CASE (PALETTE);
+      CASE (PENDATA);
+      CASE (RIFF);
+      CASE (SYLK);
+      CASE (TEXT);
+      CASE (WAVE);
+      CASE (TIFF);
+      CASE (UNICODETEXT);
+    default:
+      if (format >= CF_GDIOBJFIRST &&
+         format <= CF_GDIOBJLAST)
+       return static_printf ("CF_GDIOBJ%d", format - CF_GDIOBJFIRST);
+      if (format >= CF_PRIVATEFIRST &&
+         format <= CF_PRIVATELAST)
+       return static_printf ("CF_PRIVATE%d", format - CF_PRIVATEFIRST);
+      if (GetClipboardFormatName (format, buf, sizeof (buf)))
+       return static_printf ("%s", buf);
+      else
+       return static_printf ("unk-%#lx", format);
+    }
+}
+      
+gchar *
+_gdk_win32_data_to_string (const guchar *data,
+                          int           nbytes)
+{
+  GString *s = g_string_new ("");
+  int i;
+  gchar *retval;
+
+  for (i = 0; i < nbytes; i++)
+    if (data[i] >=' ' && data[i] <= '~')
+      g_string_append_printf (s, "%c  ", data[i]);
+    else
+      g_string_append_printf (s, "%02X ", data[i]);
+
+  retval = static_printf ("%s", s->str);
+  g_string_free (s, TRUE);
+
+  return retval;
+}
 
 gchar *
 _gdk_win32_rect_to_string (const RECT *rect)
index 745d1b4cafad536adac8dfe5a61959550057b439..0d1ab272def6efbf280bef09c6c8a99cdcc53efc 100644 (file)
@@ -401,6 +401,9 @@ gchar *_gdk_win32_psendcap_to_string   (DWORD        pen_style);
 gchar *_gdk_win32_psjoin_to_string     (DWORD        pen_style);
 gchar *_gdk_win32_message_to_string    (UINT         msg);
 gchar *_gdk_win32_key_to_string        (LONG         lParam);
+gchar *_gdk_win32_cf_to_string         (UINT         format);
+gchar *_gdk_win32_data_to_string       (const guchar*data,
+                                       int          nbytes);
 gchar *_gdk_win32_rect_to_string       (const RECT  *rect);
 
 gchar *_gdk_win32_gdkrectangle_to_string (const GdkRectangle *rect);
@@ -473,12 +476,13 @@ extern gboolean            _gdk_keyboard_has_altgr;
 extern WORD             _cf_rtf;
 extern WORD             _cf_utf8_string;
 
-/* GdkAtoms: Targets */
+/* GdkAtoms: targets */
 extern GdkAtom           _utf8_string;
-extern GdkAtom          _compound_text;
-extern GdkAtom          _text_uri_list;
 extern GdkAtom          _targets;
 
+extern GdkAtom          _text_uri_list;
+extern GdkAtom          _image_bmp;
+
 /* DND selections */
 extern GdkAtom           _local_dnd;
 extern GdkAtom          _gdk_win32_dropfiles;
@@ -500,6 +504,17 @@ extern gboolean             _sizemove_in_progress;
 /* TRUE when we are emptying the clipboard ourselves */
 extern gboolean                _ignore_destroy_clipboard;
 
+/* Mapping from registered clipboard format id (native) to
+ * corresponding GdkAtom
+ */
+extern GHashTable      *_format_atom_table;
+
+/* Hold the result of a delayed rendering */
+extern HGLOBAL         _delayed_rendering_data;
+
+HGLOBAL _gdk_win32_selection_convert_to_dib (HGLOBAL  hdata,
+                                            GdkAtom  target);
+
 /* Initialization */
 void _gdk_windowing_window_init (void);
 void _gdk_root_window_size_init (void);
index 5fb34bc5eafab28c9993db4372fd7a8289446d8d..145271216c0e6b1c9ce430456523f27e32d1ace7 100644 (file)
@@ -265,7 +265,7 @@ gdk_property_change (GdkWindow    *window,
   GDK_NOTE (DND,
            (prop_name = gdk_atom_name (property),
             type_name = gdk_atom_name (type),
-            g_print ("gdk_property_change: %p %#x (%s) %#x (%s) %s %d*%d bytes %.10s\n",
+            g_print ("gdk_property_change: %p %#x (%s) %#x (%s) %s %d*%d bytes: %s\n",
                      GDK_WINDOW_HWND (window),
                      (guint) property, prop_name,
                      (guint) type, type_name,
@@ -273,201 +273,221 @@ gdk_property_change (GdkWindow    *window,
                       (mode == GDK_PROP_MODE_PREPEND ? "PREPEND" :
                        (mode == GDK_PROP_MODE_APPEND ? "APPEND" :
                         "???"))),
-                     format, nelements, data),
+                     format, nelements,
+                     _gdk_win32_data_to_string (data, MIN (10, format*nelements/8))),
             g_free (prop_name),
             g_free (type_name)));
 
   if (property == _gdk_selection_property
-      && ((type == GDK_TARGET_STRING && GetACP () == 1252) ||
-         type == _utf8_string)
       && format == 8
       && mode == GDK_PROP_MODE_REPLACE)
     {
-      if (!OpenClipboard (GDK_WINDOW_HWND (window)))
+      if ((type == GDK_TARGET_STRING && GetACP () == 1252) ||
+         type == _utf8_string)
        {
-         WIN32_API_FAILED ("OpenClipboard");
-         return;
-       }
+         if (!OpenClipboard (GDK_WINDOW_HWND (window)))
+           {
+             WIN32_API_FAILED ("OpenClipboard");
+             return;
+           }
 
-      if (type == _utf8_string)
-       {
-         /* Check if only ASCII */
-         for (i = 0; i < nelements; i++)
-           if (data[i] >= 0200)
-             break;
-       }
-      else /* if (type == GDK_TARGET_STRING) */
-       {
-         /* Check that no 0200..0240 chars present, as they
-          * differ between ISO-8859-1 and CP1252.
-          */
-         for (i = 0; i < nelements; i++)
-           if (data[i] >= 0200 && data[i] < 0240)
-             break;
-       }
-      nchars = g_utf8_strlen (data, nelements);
+         if (type == _utf8_string)
+           {
+             /* Check if only ASCII */
+             for (i = 0; i < nelements; i++)
+               if (data[i] >= 0200)
+                 break;
+           }
+         else /* if (type == GDK_TARGET_STRING) */
+           {
+             /* Check that no 0200..0240 chars present, as they
+              * differ between ISO-8859-1 and CP1252.
+              */
+             for (i = 0; i < nelements; i++)
+               if (data[i] >= 0200 && data[i] < 0240)
+                 break;
+           }
+         nchars = g_utf8_strlen (data, nelements);
 
-      if (i == nelements)
-       {
-         /* If UTF-8 and only ASCII, or if STRING (ISO-8859-1) and
-          * system codepage is CP1252, use CF_TEXT and the data as
-          * such.
-          */
-         method = SYSTEM_CODEPAGE;
-         size = nelements;
-         for (i = 0; i < nelements; i++)
-           if (data[i] == '\n')
+         if (i == nelements)
+           {
+             /* If UTF-8 and only ASCII, or if STRING (ISO-8859-1)
+              * and system codepage is CP1252, 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++;
-         size++;
-         GDK_NOTE (DND, g_print ("... as text: %.40s\n", data));
-       }
-      else if (G_WIN32_IS_NT_BASED ())
-       {
-         /* On NT, use CF_UNICODETEXT if any non-system codepage char
-          * present.
-          */
-         method = UNICODE_TEXT;
+             GDK_NOTE (DND, g_print ("... as text: %.40s\n", data));
+           }
+         else if (G_WIN32_IS_NT_BASED ())
+           {
+             /* On NT, use CF_UNICODETEXT if any non-system codepage
+              * char present.
+              */
+             method = UNICODE_TEXT;
 
-         wcptr = g_utf8_to_utf16 (data, nelements, NULL, &wclen, NULL);
+             wcptr = g_utf8_to_utf16 (data, nelements, NULL, &wclen, NULL);
 
-         wclen++;              /* Terminating 0 */
-         size = wclen * 2;
-         GDK_NOTE (DND, g_print ("... as Unicode\n"));
-       }
-      else if (find_common_locale (data, nelements, nchars, &lcid, &buf, &size))
-       {
-         /* On Win9x, if all chars are in the default code page of
-          * some installed locale, use CF_TEXT and CF_LOCALE.
-          */
-         method = SINGLE_LOCALE;
-         GDK_NOTE (DND, g_print ("... as text in locale %#lx %d bytes\n",
-                                 (gulong) lcid, size));
-       }
-      else
-       {
-         /* On Win9x, otherwise use RTF */
+             wclen++;          /* Terminating 0 */
+             size = wclen * 2;
+             GDK_NOTE (DND, g_print ("... as Unicode\n"));
+           }
+         else if (find_common_locale (data, nelements, nchars, &lcid, &buf, &size))
+           {
+             /* On Win9x, if all chars are in the default code page
+              * of some installed locale, use CF_TEXT and CF_LOCALE.
+              */
+             method = SINGLE_LOCALE;
+             GDK_NOTE (DND, g_print ("... as text in locale %#lx %d bytes\n",
+                                     (gulong) lcid, size));
+           }
+         else
+           {
+             /* On Win9x, otherwise use RTF */
+
+             const guchar *p = data;
+
+             method = RICH_TEXT;
+             rtf = g_string_new ("{\\rtf1\\uc0 ");
 
-         const guchar *p = data;
+             while (p < data + nelements)
+               {
+                 if (*p == '{' ||
+                     *p == '\\' ||
+                     *p == '}')
+                   {
+                     rtf = g_string_append_c (rtf, '\\');
+                     rtf = g_string_append_c (rtf, *p);
+                     p++;
+                   }
+                 else if (*p < 0200 && *p >= ' ')
+                   {
+                     rtf = g_string_append_c (rtf, *p);
+                     p++;
+                   }
+                 else
+                   {
+                     guchar *q;
+                     gint n;
+                     
+                     rtf = g_string_append (rtf, "\\uNNNNN ");
+                     rtf->len -= 6; /* five digits and a space */
+                     q = rtf->str + rtf->len;
+                     n = g_sprintf (q, "%d ", g_utf8_get_char (p));
+                     g_assert (n <= 6);
+                     rtf->len += n;
+                     
+                     p = g_utf8_next_char (p);
+                   }
+               }
+             rtf = g_string_append (rtf, "}");
+             size = rtf->len + 1;
+             GDK_NOTE (DND, g_print ("... as RTF: %.40s\n", rtf->str));
+           }
+         
+         if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
+           {
+             WIN32_API_FAILED ("GlobalAlloc");
+             if (!CloseClipboard ())
+               WIN32_API_FAILED ("CloseClipboard");
+             if (buf != NULL)
+               g_free (buf);
+             if (rtf != NULL)
+               g_string_free (rtf, TRUE);
+             return;
+           }
 
-         method = RICH_TEXT;
-         rtf = g_string_new ("{\\rtf1\\uc0 ");
+         ucptr = GlobalLock (hdata);
 
-         while (p < data + nelements)
+         switch (method)
            {
-             if (*p == '{' ||
-                 *p == '\\' ||
-                 *p == '}')
+           case SYSTEM_CODEPAGE:
+             cf = CF_TEXT;
+             for (i = 0; i < nelements; i++)
                {
-                 rtf = g_string_append_c (rtf, '\\');
-                 rtf = g_string_append_c (rtf, *p);
-                 p++;
+                 if (data[i] == '\n')
+                   *ucptr++ = '\r';
+                 *ucptr++ = data[i];
                }
-             else if (*p < 0200 && *p >= ' ')
+             *ucptr++ = '\0';
+             break;
+
+           case UNICODE_TEXT:
+             cf = CF_UNICODETEXT;
+             memmove (ucptr, wcptr, size);
+             g_free (wcptr);
+             break;
+
+           case SINGLE_LOCALE:
+             cf = CF_TEXT;
+             memmove (ucptr, buf, size);
+             g_free (buf);
+
+             /* Set the CF_LOCALE clipboard data, too */
+             if (!(hlcid = GlobalAlloc (GMEM_MOVEABLE, sizeof (LCID))))
+               WIN32_API_FAILED ("GlobalAlloc"), ok = FALSE;
+             if (ok)
                {
-                 rtf = g_string_append_c (rtf, *p);
-                 p++;
+                 lcidptr = GlobalLock (hlcid);
+                 *lcidptr = lcid;
+                 GlobalUnlock (hlcid);
+                 if (!SetClipboardData (CF_LOCALE, hlcid))
+                   WIN32_API_FAILED ("SetClipboardData (CF_LOCALE)"), ok = FALSE;
                }
+             break;
+
+           case RICH_TEXT:
+             cf = _cf_rtf;
+             memmove (ucptr, rtf->str, size);
+             g_string_free (rtf, TRUE);
+
+             /* Set the UTF8_STRING clipboard data, too, for other
+              * GTK+ apps to use (won't bother reading RTF).
+              */
+             if (!(hutf8 = GlobalAlloc (GMEM_MOVEABLE, nelements)))
+               WIN32_API_FAILED ("GlobalAlloc");
              else
                {
-                 guchar *q;
-                 gint n;
-                 
-                 rtf = g_string_append (rtf, "\\uNNNNN ");
-                 rtf->len -= 6; /* five digits and a space */
-                 q = rtf->str + rtf->len;
-                 n = g_sprintf (q, "%d ", g_utf8_get_char (p));
-                 g_assert (n <= 6);
-                 rtf->len += n;
-                 
-                 p = g_utf8_next_char (p);
+                 guchar *utf8ptr = GlobalLock (hutf8);
+                 memmove (utf8ptr, data, nelements);
+                 GlobalUnlock (hutf8);
+                 if (!SetClipboardData (_cf_utf8_string, hutf8))
+                   WIN32_API_FAILED ("SetClipboardData (UTF8_STRING)");
                }
+             break;
+
+           default:
+             g_assert_not_reached ();
            }
-         rtf = g_string_append (rtf, "}");
-         size = rtf->len + 1;
-         GDK_NOTE (DND, g_print ("... as RTF: %.40s\n", rtf->str));
-       }
-         
-      if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
-       {
-         WIN32_API_FAILED ("GlobalAlloc");
+
+         GlobalUnlock (hdata);
+         if (ok && !SetClipboardData (cf, hdata))
+           WIN32_API_FAILED ("SetClipboardData"), ok = FALSE;
+      
          if (!CloseClipboard ())
            WIN32_API_FAILED ("CloseClipboard");
-         if (buf != NULL)
-           g_free (buf);
-         if (rtf != NULL)
-           g_string_free (rtf, TRUE);
-         return;
        }
-
-      ucptr = GlobalLock (hdata);
-
-      switch (method)
-       {
-       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:
-         cf = CF_UNICODETEXT;
-         memmove (ucptr, wcptr, size);
-         g_free (wcptr);
-         break;
-
-       case SINGLE_LOCALE:
-         cf = CF_TEXT;
-         memmove (ucptr, buf, size);
-         g_free (buf);
-
-         /* Set the CF_LOCALE clipboard data, too */
-         if (!(hlcid = GlobalAlloc (GMEM_MOVEABLE, sizeof (LCID))))
-           WIN32_API_FAILED ("GlobalAlloc"), ok = FALSE;
-         if (ok)
-           {
-             lcidptr = GlobalLock (hlcid);
-             *lcidptr = lcid;
-             GlobalUnlock (hlcid);
-             if (!SetClipboardData (CF_LOCALE, hlcid))
-               WIN32_API_FAILED ("SetClipboardData (CF_LOCALE)"), ok = FALSE;
-           }
-         break;
-
-       case RICH_TEXT:
-         cf = _cf_rtf;
-         memmove (ucptr, rtf->str, size);
-         g_string_free (rtf, TRUE);
-
-         /* Set the UTF8_STRING clipboard data, too, for other
-          * GTK+ apps to use (won't bother reading RTF).
+      else
+        {
+         /* 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.
           */
-         if (!(hutf8 = GlobalAlloc (GMEM_MOVEABLE, nelements)))
-           WIN32_API_FAILED ("GlobalAlloc");
-         else
+         _delayed_rendering_data = NULL;
+         if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, nelements > 0 ? nelements : 1)))
            {
-             guchar *utf8ptr = GlobalLock (hutf8);
-             memmove (utf8ptr, data, nelements);
-             GlobalUnlock (hutf8);
-             if (!SetClipboardData (_cf_utf8_string, hutf8))
-               WIN32_API_FAILED ("SetClipboardData (UTF8_STRING)");
+             WIN32_API_FAILED ("GlobalAlloc");
+             return;
            }
-         break;
-
-       default:
-         g_assert_not_reached ();
+         ucptr = GlobalLock (hdata);
+         memcpy (ucptr, data, nelements);
+         GlobalUnlock (hdata);
+         _delayed_rendering_data = hdata;
        }
-
-      GlobalUnlock (hdata);
-      if (ok && !SetClipboardData (cf, hdata))
-       WIN32_API_FAILED ("SetClipboardData"), ok = FALSE;
-      
-      if (!CloseClipboard ())
-       WIN32_API_FAILED ("CloseClipboard");
     }
   else
     g_warning ("gdk_property_change: General case not implemented");
@@ -592,13 +612,15 @@ gdk_screen_get_setting (GdkScreen   *screen,
       ncm.cbSize = sizeof(NONCLIENTMETRICS);
       if (SystemParametersInfo (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, FALSE))
         {
-          /* Pango finally uses GetDeviceCaps to scale, we use simple approximation here */
+          /* Pango finally uses GetDeviceCaps to scale, we use simple
+          * approximation here.
+          */
           int nHeight = (0 > ncm.lfMenuFont.lfHeight ? -3*ncm.lfMenuFont.lfHeight/4 : 10);
           if (OUT_STRING_PRECIS == ncm.lfMenuFont.lfOutPrecision)
             GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) : ignoring bitmap font '%s'\n", 
                                    name, ncm.lfMenuFont.lfFaceName));
           else if (ncm.lfMenuFont.lfFaceName && strlen(ncm.lfMenuFont.lfFaceName) > 0 &&
-                   /* avoid issues like those described in bug #135098 */
+                   /* Avoid issues like those described in bug #135098 */
                    g_utf8_validate (ncm.lfMenuFont.lfFaceName, -1, NULL))
             {
               char* s = g_strdup_printf ("%s %d", ncm.lfMenuFont.lfFaceName, nHeight);
index 31eab06c8b43f7c9ea0512d65bc1c30c3cec7c7b..d5edb2d08b6bf877f4cb020961b38b7a4643787f 100644 (file)
@@ -60,6 +60,7 @@ _gdk_win32_selection_init (void)
 {
   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);
 }
 
 /* The specifications for COMPOUND_TEXT and STRING specify that C0 and
@@ -350,52 +351,55 @@ gdk_selection_convert (GdkWindow *requestor,
 
   if (selection == GDK_SELECTION_CLIPBOARD && target == _targets)
     {
-      /* He wants to know what formats are on the clipboard.  If there
+      gint formats_cnt, i, fmt;
+      GdkAtom *data;
+      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))
        {
-         GdkAtom *data = g_new (GdkAtom, 1);
-         *data = _utf8_string;
-         _gdk_selection_property_store (requestor, GDK_SELECTION_TYPE_ATOM,
-                                        32, (guchar *) data, 1 * sizeof (GdkAtom));
-       }
-      else if (IsClipboardFormatAvailable (CF_BITMAP) ||
-               IsClipboardFormatAvailable (CF_DIB))
-       {
-         GdkAtom *data = g_new (GdkAtom, 1);
-         GdkAtom atom = gdk_atom_intern ("image/bmp", FALSE);
-          *data = atom;
-         _gdk_selection_property_store (requestor, GDK_SELECTION_TYPE_ATOM,
-                                        32, (guchar *) data, 1 * sizeof (GdkAtom));
+         data[i++] = _utf8_string;
        }
-      else if (CountClipboardFormats() > 0)
+      if (formats_cnt > 0)
         {
-          /* if there is anything else in the clipboard, enum it all although we don't 
-           * offer special conversion services 
+          /* If there is anything else in the clipboard, enum it all
+           * although we don't offer special conversion services.
            */
-          int fmt = 0, i = 0;
-         GdkAtom *data = g_new (GdkAtom, CountClipboardFormats());
-
-          for ( ; 0 != (fmt = EnumClipboardFormats (fmt)); )
+          for (fmt = 0; 0 != (fmt = EnumClipboardFormats (fmt)); )
             {
-              char sFormat[80];
+              gchar sFormat[80];
 
-              if (GetClipboardFormatName (fmt, sFormat, 80) > 0)
+              if (GetClipboardFormatName (fmt, sFormat, 80) > 0 &&
+                 strcmp (sFormat, "UTF8_STRING"))
                 {
+                 if (!has_bmp &&
+                     (!strcmp (sFormat, "image/bmp") ||
+                      !strcmp (sFormat, "image/x-bmp") ||
+                      !strcmp (sFormat, "image/x-MS-bmp")))
+                   has_bmp = TRUE;
                   GdkAtom atom = gdk_atom_intern (sFormat, FALSE);
-                  data[i] = atom;
-                  i++;
+                  data[i++] = atom;
                 }
             }
+        }
+      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             
        property = GDK_NONE;
 
@@ -542,21 +546,42 @@ gdk_selection_convert (GdkWindow *requestor,
       API_CALL (CloseClipboard, ());
     }
   else if (selection == GDK_SELECTION_CLIPBOARD &&
-           target == gdk_atom_intern ("image/bmp", TRUE))
+           target == _image_bmp)
     {
+      guchar *data;
+
       if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
        return;
-      if ((hdata = GetClipboardData (CF_DIB)) != NULL)
+      if ((hdata = GetClipboardData (RegisterClipboardFormat ("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 there's CF_DIB but not "image/bmp", the clipboard
+          * owner is probably a native Win32 application.
+          */
           BITMAPINFOHEADER *ptr;
-          guchar *data;
 
           if ((ptr = GlobalLock (hdata)) != NULL)
             {
-              BITMAPFILEHEADER *hdr; /* need to add a file header so gdk-pixbuf can load it */
-             gint length = GlobalSize (hdata) + sizeof(BITMAPFILEHEADER);
+              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: %d bytes\n", length));
+             GDK_NOTE (DND, g_print ("... BITMAP (from CF_DIB): %d bytes\n", length));
              
               data = g_try_malloc (length);
               if (data)
@@ -564,16 +589,16 @@ gdk_selection_convert (GdkWindow *requestor,
                   hdr = (BITMAPFILEHEADER *)data;
                   hdr->bfType = 0x4d42; /* 0x42 = "B" 0x4d = "M" */
                   /* Compute the size of the entire file. */
-                  hdr->bfSize = (DWORD) (sizeof(BITMAPFILEHEADER)
+                  hdr->bfSize = (DWORD) (sizeof (BITMAPFILEHEADER)
                         + ptr->biSize + ptr->biClrUsed
-                       * sizeof(RGBQUAD) + ptr->biSizeImage);
+                       * sizeof (RGBQUAD) + ptr->biSizeImage);
                   hdr->bfReserved1 = 0;
                   hdr->bfReserved2 = 0;
                   /* Compute the offset to the array of color indices. */
-                  hdr->bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER)
+                  hdr->bfOffBits = (DWORD) sizeof (BITMAPFILEHEADER)
                         + ptr->biSize + ptr->biClrUsed * sizeof (RGBQUAD);
-                  /* copy the data behind it */
-                  memcpy (data + sizeof(BITMAPFILEHEADER), ptr, length - sizeof(BITMAPFILEHEADER));
+                  /* Copy the data behind it */
+                  memcpy (data + sizeof (BITMAPFILEHEADER), ptr, length - sizeof (BITMAPFILEHEADER));
                  _gdk_selection_property_store (requestor, target, 8,
                                                 data, length);
                 }
@@ -591,7 +616,12 @@ gdk_selection_convert (GdkWindow *requestor,
 
       if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
        return;
-      /* check if its available */
+      /* Check if it's available. In fact, we can 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
+       * are just a requestor.
+       */
       for ( ; 0 != (fmt = EnumClipboardFormats (fmt)); )
         {
           char sFormat[80];
@@ -601,7 +631,7 @@ gdk_selection_convert (GdkWindow *requestor,
             {
               if ((hdata = GetClipboardData (fmt)) != NULL)
                {
-                 /* simply get it without conversion */
+                 /* Simply get it without conversion */
                   guchar *ptr;
                   gint length;
 
@@ -673,7 +703,8 @@ gdk_selection_property_get (GdkWindow  *requestor,
       return 0;
     }
 
-  *data = g_malloc (prop->length);
+  *data = g_malloc (prop->length + 1);
+  (*data)[prop->length] = '\0';
   if (prop->length > 0)
     memmove (*data, prop->data, prop->length);
 
@@ -713,7 +744,6 @@ gdk_selection_send_notify_for_display (GdkDisplay *display,
                                        GdkAtom     property,
                                        guint32     time)
 {
-  GdkEvent tmp_event;
   gchar *sel_name, *tgt_name, *prop_name;
 
   g_return_if_fail (display == _gdk_display);
@@ -968,3 +998,174 @@ gdk_free_compound_text (guchar *ctext)
    */
   g_return_if_fail (ctext == NULL);
 }
+
+void
+gdk_win32_selection_add_targets (GdkWindow  *owner,
+                                GdkAtom     selection,
+                                gint        n_targets,
+                                GdkAtom    *targets)
+{
+  HWND hwnd;
+  const gchar *target_name;
+  guint formatid;
+  gint i;
+  GSList *convertable_formats, *format;
+  gboolean has_set_dib = FALSE, has_real_dib = FALSE;
+
+  if (selection != GDK_SELECTION_CLIPBOARD)
+    return;
+
+  if (owner != NULL)
+    {
+      if (GDK_WINDOW_DESTROYED (owner))
+       return;
+      hwnd = GDK_WINDOW_HWND (owner);
+    }
+
+  if (!API_CALL (OpenClipboard, (hwnd)))
+    return;
+
+  convertable_formats = gdk_pixbuf_get_formats ();
+  for (i = 0; i < n_targets; ++i)
+    {
+      if (targets[i] == _utf8_string)
+       continue;
+
+      target_name = gdk_atom_name (targets[i]);
+      if (!(formatid = RegisterClipboardFormat (target_name))) {
+       WIN32_API_FAILED ("RegisterClipboardFormat");
+       API_CALL (CloseClipboard, ());
+       return;
+      }
+      g_hash_table_replace (_format_atom_table, GINT_TO_POINTER (formatid), targets[i]);
+      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")))
+       {
+         g_hash_table_replace (_format_atom_table,
+                               GINT_TO_POINTER (CF_DIB),
+                               targets[i]);
+         if (!has_set_dib) {
+           SetClipboardData (CF_DIB, NULL);
+           has_set_dib = TRUE;
+         }
+         has_real_dib = TRUE;
+         continue;
+       }
+
+      for (format = convertable_formats; !has_set_dib && format; format = format->next)
+       {
+         gchar **mime_types =
+           gdk_pixbuf_format_get_mime_types ((GdkPixbufFormat *) format->data);
+
+         for (; *mime_types; ++mime_types)
+           {
+             if (!strcmp (target_name, *mime_types))
+               {
+                 g_hash_table_replace (_format_atom_table,
+                                       GINT_TO_POINTER (CF_DIB),
+                                       targets[i]);
+                 SetClipboardData (CF_DIB, NULL);
+                 has_set_dib = TRUE;
+                 break;
+               }
+           }
+       }
+    }
+  g_slist_free (convertable_formats);
+
+  API_CALL (CloseClipboard, ());
+}
+
+/* Convert from types such as "image/jpg" or "image/png" to DIB using
+ * gdk-pixbuf so that image copied from GTK+ apps can be pasted in
+ * native apps like mspaint.exe
+ */
+HGLOBAL
+_gdk_win32_selection_convert_to_dib (HGLOBAL  hdata,
+                                    GdkAtom  target)
+{
+  GdkPixbufLoader *loader;
+  GdkPixbuf *pixbuf;
+  const 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"))
+    {
+      /* No conversion is needed, just strip the BITMAPFILEHEADER */
+      HGLOBAL hdatanew;
+
+      size = GlobalSize (hdata) - 1 - sizeof (BITMAPFILEHEADER);
+      ptr = GlobalLock (hdata);
+      memmove (ptr, ptr + sizeof (BITMAPFILEHEADER), size);
+      GlobalUnlock (hdata);
+      if (!(hdatanew = GlobalReAlloc (hdata, size, 0))) {
+       WIN32_API_FAILED ("GlobalReAlloc");
+       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);
+      return NULL;
+    }
+
+  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);
+    }
+
+  return hdata;
+}
index bae4708adbdb7871459582261822fce1f63616b8..14c91baa4671abef677090f01e90b741e00e832b 100644 (file)
@@ -79,6 +79,11 @@ void          gdk_win32_hdc_release  (GdkDrawable    *drawable,
                                      GdkGC          *gc,
                                      GdkGCValuesMask usage);
 
+void          gdk_win32_selection_add_targets (GdkWindow  *owner,
+                                              GdkAtom     selection,
+                                              gint        n_targets,
+                                              GdkAtom    *targets);
+
 G_END_DECLS
 
 #endif /* __GDK_WIN32_H__ */
index e119df308a3cc54641021595686e4f35a64091f1..328c5d390183f706f04ae986af70fac53944c7d4 100644 (file)
 #include "x11/gdkx.h"
 #endif
 
+#ifdef GDK_WINDOWING_WIN32
+#include "win32/gdkwin32.h"
+#endif
+
 #include "gtkalias.h"
 
 #undef DEBUG_SELECTION
@@ -750,6 +754,9 @@ gtk_selection_add_target (GtkWidget     *widget,
 
   list = gtk_selection_target_list_get (widget, selection);
   gtk_target_list_add (list, target, 0, info);
+#ifdef GDK_WINDOWING_WIN32
+  gdk_win32_selection_add_targets (widget->window, selection, 1, &target);
+#endif
 }
 
 /**
@@ -776,6 +783,18 @@ gtk_selection_add_targets (GtkWidget            *widget,
   
   list = gtk_selection_target_list_get (widget, selection);
   gtk_target_list_add_table (list, targets, ntargets);
+
+#ifdef GDK_WINDOWING_WIN32
+  {
+    int i;
+    GdkAtom *atoms = g_new (GdkAtom, ntargets);
+
+    for (i = 0; i < ntargets; ++i)
+      atoms[i] = gdk_atom_intern (targets[i].target, FALSE);
+    gdk_win32_selection_add_targets (widget->window, selection, ntargets, atoms);
+    g_free (atoms);
+  }
+#endif
 }