1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * Copyright (C) 1998-2002 Tor Lillqvist
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
21 * file for a list of people on the GTK+ Team. See the ChangeLog
22 * files for a list of changes. These files are distributed with
23 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
30 #include "gdkproperty.h"
31 #include "gdkselection.h"
32 #include "gdkdisplay.h"
33 #include "gdkprivate-win32.h"
36 /* We emulate the GDK_SELECTION window properties of windows (as used
37 * in the X11 backend) by using a hash table from window handles to
48 static GHashTable *sel_prop_table = NULL;
50 static GdkSelProp *dropfiles_prop = NULL;
52 /* We store the owner of each selection in this table. Obviously, this only
53 * is valid intra-app, and in fact it is necessary for the intra-app DND to work.
55 static GHashTable *sel_owner_table = NULL;
57 /* GdkAtoms for well-known image formats */
58 static GdkAtom *known_pixbuf_formats;
59 static int n_known_pixbuf_formats;
61 /* GdkAtoms for well-known text formats */
62 static GdkAtom text_plain;
63 static GdkAtom text_plain_charset_utf_8;
64 static GdkAtom text_plain_charset_CP1252;
67 _gdk_win32_selection_init (void)
69 GSList *pixbuf_formats;
72 sel_prop_table = g_hash_table_new (NULL, NULL);
73 sel_owner_table = g_hash_table_new (NULL, NULL);
74 _format_atom_table = g_hash_table_new (NULL, NULL);
76 pixbuf_formats = gdk_pixbuf_get_formats ();
78 n_known_pixbuf_formats = 0;
79 for (rover = pixbuf_formats; rover != NULL; rover = rover->next)
82 gdk_pixbuf_format_get_mime_types ((GdkPixbufFormat *) rover->data);
86 for (mime_type = mime_types; *mime_type != NULL; mime_type++)
87 n_known_pixbuf_formats++;
90 known_pixbuf_formats = g_new (GdkAtom, n_known_pixbuf_formats);
92 n_known_pixbuf_formats = 0;
93 for (rover = pixbuf_formats; rover != NULL; rover = rover->next)
96 gdk_pixbuf_format_get_mime_types ((GdkPixbufFormat *) rover->data);
100 for (mime_type = mime_types; *mime_type != NULL; mime_type++)
101 known_pixbuf_formats[n_known_pixbuf_formats++] = gdk_atom_intern (*mime_type, FALSE);
104 g_slist_free (pixbuf_formats);
106 text_plain = gdk_atom_intern ("text/plain", FALSE);
107 text_plain_charset_utf_8= gdk_atom_intern ("text/plain;charset=utf-8", FALSE);
108 text_plain_charset_CP1252 = gdk_atom_intern ("text/plain;charset=CP1252", FALSE);
110 g_hash_table_replace (_format_atom_table,
111 GINT_TO_POINTER (_cf_png),
114 g_hash_table_replace (_format_atom_table,
115 GINT_TO_POINTER (CF_DIB),
119 /* The specifications for COMPOUND_TEXT and STRING specify that C0 and
120 * C1 are not allowed except for \n and \t, however the X conversions
121 * routines for COMPOUND_TEXT only enforce this in one direction,
122 * causing cut-and-paste of \r and \r\n separated text to fail.
123 * This routine strips out all non-allowed C0 and C1 characters
124 * from the input string and also canonicalizes \r, and \r\n to \n
127 sanitize_utf8 (const gchar *src,
130 GString *result = g_string_sized_new (length + 1);
131 const gchar *p = src;
132 const gchar *endp = src + length;
142 g_string_append_c (result, '\n');
146 gunichar ch = g_utf8_get_char (p);
150 if (!((ch < 0x20 && ch != '\t' && ch != '\n') || (ch >= 0x7f && ch < 0xa0)))
152 buflen = g_unichar_to_utf8 (ch, buf);
153 g_string_append_len (result, buf, buflen);
156 p = g_utf8_next_char (p);
159 g_string_append_c (result, '\0');
161 return g_string_free (result, FALSE);
165 _gdk_utf8_to_string_target_internal (const gchar *str,
168 GError *error = NULL;
170 gchar *tmp_str = sanitize_utf8 (str, length);
171 gchar *result = g_convert_with_fallback (tmp_str, -1,
172 "ISO-8859-1", "UTF-8",
173 NULL, NULL, NULL, &error);
176 g_warning ("Error converting from UTF-8 to STRING: %s",
178 g_error_free (error);
186 selection_property_store (GdkWindow *owner,
194 g_return_if_fail (type != GDK_TARGET_STRING);
196 prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (owner));
202 g_hash_table_remove (sel_prop_table, GDK_WINDOW_HWND (owner));
205 prop = g_new (GdkSelProp, 1);
208 prop->length = length;
209 prop->format = format;
212 g_hash_table_insert (sel_prop_table, GDK_WINDOW_HWND (owner), prop);
216 _gdk_dropfiles_store (gchar *data)
220 g_assert (dropfiles_prop == NULL);
222 dropfiles_prop = g_new (GdkSelProp, 1);
223 dropfiles_prop->data = (guchar *) data;
224 dropfiles_prop->length = strlen (data) + 1;
225 dropfiles_prop->format = 8;
226 dropfiles_prop->type = _text_uri_list;
230 if (dropfiles_prop != NULL)
232 g_free (dropfiles_prop->data);
233 g_free (dropfiles_prop);
235 dropfiles_prop = NULL;
240 get_mapped_gdk_atom_name (GdkAtom gdk_target)
242 if (gdk_target == _image_png)
243 return g_strdup ("PNG");
245 if (gdk_target == _image_jpeg)
246 return g_strdup ("JFIF");
248 if (gdk_target == _image_gif)
249 return g_strdup ("GIF");
251 return gdk_atom_name (gdk_target);
255 _gdk_win32_display_set_selection_owner (GdkDisplay *display,
264 g_return_val_if_fail (display == _gdk_display, FALSE);
265 g_return_val_if_fail (selection != GDK_NONE, FALSE);
268 gchar *sel_name = gdk_atom_name (selection);
270 g_print ("gdk_selection_owner_set_for_display: %p %s\n",
271 (owner ? GDK_WINDOW_HWND (owner) : NULL),
276 if (selection != GDK_SELECTION_CLIPBOARD)
279 g_hash_table_insert (sel_owner_table, selection, GDK_WINDOW_HWND (owner));
281 g_hash_table_remove (sel_owner_table, selection);
285 /* Rest of this function handles the CLIPBOARD selection */
288 if (GDK_WINDOW_DESTROYED (owner))
291 hwnd = GDK_WINDOW_HWND (owner);
296 if (!API_CALL (OpenClipboard, (hwnd)))
299 _ignore_destroy_clipboard = TRUE;
300 GDK_NOTE (DND, g_print ("... EmptyClipboard()\n"));
301 if (!API_CALL (EmptyClipboard, ()))
303 _ignore_destroy_clipboard = FALSE;
304 API_CALL (CloseClipboard, ());
307 _ignore_destroy_clipboard = FALSE;
309 if (!API_CALL (CloseClipboard, ()))
314 /* Send ourselves a selection request message so that
315 * gdk_property_change will be called to store the clipboard
318 GDK_NOTE (DND, g_print ("... sending GDK_SELECTION_REQUEST to ourselves\n"));
319 tmp_event.selection.type = GDK_SELECTION_REQUEST;
320 tmp_event.selection.window = owner;
321 tmp_event.selection.send_event = FALSE;
322 tmp_event.selection.selection = selection;
323 tmp_event.selection.target = _utf8_string;
324 tmp_event.selection.property = _gdk_selection;
325 tmp_event.selection.requestor = gdk_win32_handle_table_lookup (hwnd);
326 tmp_event.selection.time = time;
328 gdk_event_put (&tmp_event);
335 _gdk_win32_display_get_selection_owner (GdkDisplay *display,
340 g_return_val_if_fail (display == _gdk_display, NULL);
341 g_return_val_if_fail (selection != GDK_NONE, NULL);
343 if (selection == GDK_SELECTION_CLIPBOARD)
345 HWND owner = GetClipboardOwner ();
350 return gdk_win32_handle_table_lookup (owner);
353 window = gdk_win32_window_lookup_for_display (display,
354 g_hash_table_lookup (sel_owner_table, selection));
357 gchar *sel_name = gdk_atom_name (selection);
359 g_print ("gdk_selection_owner_get: %s = %p\n",
361 (window ? GDK_WINDOW_HWND (window) : NULL));
369 generate_selection_notify (GdkWindow *requestor,
377 tmp_event.selection.type = GDK_SELECTION_NOTIFY;
378 tmp_event.selection.window = requestor;
379 tmp_event.selection.send_event = FALSE;
380 tmp_event.selection.selection = selection;
381 tmp_event.selection.target = target;
382 tmp_event.selection.property = property;
383 tmp_event.selection.requestor = 0;
384 tmp_event.selection.time = time;
386 gdk_event_put (&tmp_event);
390 _gdk_win32_display_convert_selection (GdkDisplay *display,
391 GdkWindow *requestor,
397 GdkAtom property = _gdk_selection;
399 g_return_if_fail (selection != GDK_NONE);
400 g_return_if_fail (requestor != NULL);
402 if (GDK_WINDOW_DESTROYED (requestor))
406 gchar *sel_name = gdk_atom_name (selection);
407 gchar *tgt_name = gdk_atom_name (target);
409 g_print ("gdk_selection_convert: %p %s %s\n",
410 GDK_WINDOW_HWND (requestor),
416 if (selection == GDK_SELECTION_CLIPBOARD && target == _targets)
420 gboolean has_text = FALSE;
421 gboolean has_png = FALSE;
422 gboolean has_bmp = FALSE;
424 if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
427 targets = g_new (GdkAtom, CountClipboardFormats ());
430 for (fmt = 0; 0 != (fmt = EnumClipboardFormats (fmt)); )
434 targets[ntargets++] = _image_png;
439 for (fmt = 0; 0 != (fmt = EnumClipboardFormats (fmt)); )
443 if (fmt == CF_UNICODETEXT || fmt == CF_TEXT)
445 /* Advertise text to GDK always as UTF8_STRING */
447 targets[ntargets++] = _utf8_string;
450 else if (fmt == _cf_png)
452 /* Already handled above */
454 else if (fmt == CF_DIB ||
457 /* Don't bother telling that a bitmap is present if there is
458 * also PNG, which is much more reliable in transferring
461 if (!has_bmp && !has_png)
462 targets[ntargets++] = _image_bmp;
465 else if (fmt == _cf_jfif)
469 targets[ntargets++] = _image_jpeg;
471 else if (fmt == _cf_gif)
476 targets[ntargets++] = _image_gif;
478 else if (GetClipboardFormatName (fmt, sFormat, 80) > 0)
480 if (strcmp (sFormat, "image/bmp") == 0 ||
481 strcmp (sFormat, "image/x-bmp") == 0 ||
482 strcmp (sFormat, "image/x-MS-bmp") == 0 ||
483 strcmp (sFormat, "image/x-icon") == 0 ||
484 strcmp (sFormat, "image/x-ico") == 0 ||
485 strcmp (sFormat, "image/x-win-bitmap") == 0)
487 /* Ignore these (from older GTK+ versions
488 * presumably), as the same image in the CF_DIB
489 * format will also be on the clipboard anyway.
493 targets[ntargets++] = gdk_atom_intern (sFormat, FALSE);
501 for (i = 0; i < ntargets; i++)
503 gchar *atom_name = gdk_atom_name (targets[i]);
505 g_print ("%s", atom_name);
507 if (i < ntargets - 1)
514 selection_property_store (requestor, GDK_SELECTION_TYPE_ATOM,
515 32, (guchar *) targets,
516 ntargets * sizeof (GdkAtom));
520 API_CALL (CloseClipboard, ());
522 else if (selection == GDK_SELECTION_CLIPBOARD && target == _utf8_string)
524 /* Converting the CLIPBOARD selection means he wants the
525 * contents of the clipboard. Get the clipboard data, and store
528 if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
531 if ((hdata = GetClipboardData (CF_UNICODETEXT)) != NULL)
533 wchar_t *ptr, *wcs, *p, *q;
537 if ((ptr = GlobalLock (hdata)) != NULL)
539 length = GlobalSize (hdata);
541 GDK_NOTE (DND, g_print ("... CF_UNICODETEXT: %ld bytes\n",
545 wcs = g_new (wchar_t, length / 2 + 1);
549 while (p < ptr + length / 2)
559 data = g_utf16_to_utf8 (wcs, wclen, NULL, NULL, NULL);
563 selection_property_store (requestor, _utf8_string, 8,
564 data, strlen (data) + 1);
565 GlobalUnlock (hdata);
571 API_CALL (CloseClipboard, ());
573 else if (selection == GDK_SELECTION_CLIPBOARD && target == _image_bmp)
575 if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
578 if ((hdata = GetClipboardData (CF_DIB)) != NULL)
580 BITMAPINFOHEADER *bi;
582 if ((bi = GlobalLock (hdata)) != NULL)
584 /* Need to add a BMP file header so gdk-pixbuf can load
587 * If the data is from Mozilla Firefox or IE7, and
588 * starts with an "old fashioned" BITMAPINFOHEADER,
589 * i.e. with biSize==40, and biCompression == BI_RGB and
590 * biBitCount==32, we assume that the "extra" byte in
591 * each pixel in fact is alpha.
593 * The gdk-pixbuf bmp loader doesn't trust 32-bit BI_RGB
594 * bitmaps to in fact have alpha, so we have to convince
595 * it by changing the bitmap header to a version 5
596 * BI_BITFIELDS one with explicit alpha mask indicated.
598 * The RGB bytes that are in bitmaps on the clipboard
599 * originating from Firefox or IE7 seem to be
600 * premultiplied with alpha. The gdk-pixbuf bmp loader
601 * of course doesn't expect that, so we have to undo the
602 * premultiplication before feeding the bitmap to the
605 * Note that for some reason the bmp loader used to want
606 * the alpha bytes in its input to actually be
607 * 255-alpha, but here we assume that this has been
608 * fixed before this is committed.
610 BITMAPFILEHEADER *bf;
612 gint data_length = GlobalSize (hdata);
614 gboolean make_dibv5 = FALSE;
616 GDK_NOTE (DND, g_print ("... CF_DIB: %d bytes\n", data_length));
618 if (bi->biSize == sizeof (BITMAPINFOHEADER) &&
620 bi->biBitCount == 32 &&
621 bi->biCompression == BI_RGB &&
623 /* Maybe check explicitly for Mozilla or IE7?
625 * If the clipboard format
626 * application/x-moz-nativeimage is present, that is
627 * a reliable indicator that the data is offered by
628 * Mozilla one would think. For IE7,
629 * UniformResourceLocatorW is presumably not that
630 * uniqie, so probably need to do some
631 * GetClipboardOwner(), GetWindowThreadProcessId(),
632 * OpenProcess(), GetModuleFileNameEx() dance to
635 (IsClipboardFormatAvailable
636 (RegisterClipboardFormat ("application/x-moz-nativeimage")) ||
637 IsClipboardFormatAvailable
638 (RegisterClipboardFormat ("UniformResourceLocatorW"))) &&
642 /* We turn the BITMAPINFOHEADER into a
643 * BITMAPV5HEADER before feeding it to gdk-pixbuf.
645 new_length = (data_length +
646 sizeof (BITMAPFILEHEADER) +
647 (sizeof (BITMAPV5HEADER) - sizeof (BITMAPINFOHEADER)));
652 new_length = data_length + sizeof (BITMAPFILEHEADER);
655 data = g_try_malloc (new_length);
659 bf = (BITMAPFILEHEADER *)data;
660 bf->bfType = 0x4d42; /* "BM" */
661 bf->bfSize = new_length;
667 BITMAPV5HEADER *bV5 = (BITMAPV5HEADER *) ((char *) data + sizeof (BITMAPFILEHEADER));
671 bV5->bV5Size = sizeof (BITMAPV5HEADER);
672 bV5->bV5Width = bi->biWidth;
673 bV5->bV5Height = bi->biHeight;
675 bV5->bV5BitCount = 32;
676 bV5->bV5Compression = BI_BITFIELDS;
677 bV5->bV5SizeImage = 4 * bV5->bV5Width * ABS (bV5->bV5Height);
678 bV5->bV5XPelsPerMeter = bi->biXPelsPerMeter;
679 bV5->bV5YPelsPerMeter = bi->biYPelsPerMeter;
681 bV5->bV5ClrImportant = 0;
682 /* Now the added mask fields */
683 bV5->bV5RedMask = 0x00ff0000;
684 bV5->bV5GreenMask = 0x0000ff00;
685 bV5->bV5BlueMask = 0x000000ff;
686 bV5->bV5AlphaMask = 0xff000000;
687 ((char *) &bV5->bV5CSType)[3] = 's';
688 ((char *) &bV5->bV5CSType)[2] = 'R';
689 ((char *) &bV5->bV5CSType)[1] = 'G';
690 ((char *) &bV5->bV5CSType)[0] = 'B';
691 /* Ignore colorspace and profile fields */
692 bV5->bV5Intent = LCS_GM_GRAPHICS;
693 bV5->bV5Reserved = 0;
695 bf->bfOffBits = (sizeof (BITMAPFILEHEADER) +
698 p = ((guchar *) data) + sizeof (BITMAPFILEHEADER) + sizeof (BITMAPV5HEADER);
699 memcpy (p, ((char *) bi) + bi->biSize,
700 data_length - sizeof (BITMAPINFOHEADER));
702 for (i = 0; i < bV5->bV5SizeImage/4; i++)
706 gdouble inverse_alpha = 255./p[3];
708 p[0] = p[0] * inverse_alpha + 0.5;
709 p[1] = p[1] * inverse_alpha + 0.5;
710 p[2] = p[2] * inverse_alpha + 0.5;
718 bf->bfOffBits = (sizeof (BITMAPFILEHEADER) +
720 bi->biClrUsed * sizeof (RGBQUAD));
722 if (bi->biCompression == BI_BITFIELDS && bi->biBitCount >= 16)
724 /* Screenshots taken with PrintScreen or
725 * Alt + PrintScreen are found on the clipboard in
726 * this format. In this case the BITMAPINFOHEADER is
727 * followed by three DWORD specifying the masks of the
728 * red green and blue components, so adjust the offset
730 bf->bfOffBits += (3 * sizeof (DWORD));
733 memcpy ((char *) data + sizeof (BITMAPFILEHEADER),
738 selection_property_store (requestor, _image_bmp, 8,
741 GlobalUnlock (hdata);
745 API_CALL (CloseClipboard, ());
747 else if (selection == GDK_SELECTION_CLIPBOARD)
749 gchar *mapped_target_name;
752 if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
755 mapped_target_name = get_mapped_gdk_atom_name (target);
757 /* Check if it's available. We could simply call
758 * GetClipboardData (RegisterClipboardFormat (targetname)), but
759 * the global custom format ID space is limited,
760 * (0xC000~0xFFFF), and we better not waste an format ID if we
761 * are just a requestor.
763 for ( ; 0 != (fmt = EnumClipboardFormats (fmt)); )
767 if (GetClipboardFormatName (fmt, sFormat, 80) > 0 &&
768 strcmp (sFormat, mapped_target_name) == 0)
770 if ((hdata = GetClipboardData (fmt)) != NULL)
772 /* Simply get it without conversion */
776 if ((ptr = GlobalLock (hdata)) != NULL)
778 length = GlobalSize (hdata);
780 GDK_NOTE (DND, g_print ("... %s: %d bytes\n", mapped_target_name, length));
782 selection_property_store (requestor, target, 8,
783 g_memdup (ptr, length), length);
784 GlobalUnlock (hdata);
790 g_free (mapped_target_name);
791 API_CALL (CloseClipboard, ());
793 else if (selection == _gdk_win32_dropfiles)
795 /* This means he wants the names of the dropped files.
796 * gdk_dropfiles_filter already has stored the text/uri-list
797 * data temporarily in dropfiles_prop.
799 if (dropfiles_prop != NULL)
801 selection_property_store
802 (requestor, dropfiles_prop->type, dropfiles_prop->format,
803 dropfiles_prop->data, dropfiles_prop->length);
804 g_free (dropfiles_prop);
805 dropfiles_prop = NULL;
811 /* Generate a selection notify message so that we actually fetch the
812 * data (if property == _gdk_selection) or indicating failure (if
813 * property == GDK_NONE).
815 generate_selection_notify (requestor, selection, target, property, time);
819 _gdk_win32_display_get_selection_property (GdkDisplay *display,
820 GdkWindow *requestor,
827 g_return_val_if_fail (requestor != NULL, 0);
828 g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
830 if (GDK_WINDOW_DESTROYED (requestor))
833 GDK_NOTE (DND, g_print ("gdk_selection_property_get: %p",
834 GDK_WINDOW_HWND (requestor)));
836 prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (requestor));
840 GDK_NOTE (DND, g_print (" (nothing)\n"));
846 *data = g_malloc (prop->length + 1);
847 (*data)[prop->length] = '\0';
848 if (prop->length > 0)
849 memmove (*data, prop->data, prop->length);
852 gchar *type_name = gdk_atom_name (prop->type);
854 g_print (" %s format:%d length:%d\n", type_name, prop->format, prop->length);
859 *ret_type = prop->type;
862 *ret_format = prop->format;
868 _gdk_selection_property_delete (GdkWindow *window)
870 GDK_NOTE (DND, g_print ("_gdk_selection_property_delete: %p (no-op)\n",
871 GDK_WINDOW_HWND (window)));
874 prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (window));
879 g_hash_table_remove (sel_prop_table, GDK_WINDOW_HWND (window));
885 _gdk_win32_display_send_selection_notify (GdkDisplay *display,
886 GdkWindow *requestor,
892 g_return_if_fail (display == _gdk_display);
895 gchar *sel_name = gdk_atom_name (selection);
896 gchar *tgt_name = gdk_atom_name (target);
897 gchar *prop_name = gdk_atom_name (property);
899 g_print ("gdk_selection_send_notify_for_display: %p %s %s %s (no-op)\n",
900 requestor, sel_name, tgt_name, prop_name);
907 /* It's hard to say whether implementing this actually is of any use
908 * on the Win32 platform? gtk calls only
909 * gdk_text_property_to_utf8_list_for_display().
912 gdk_text_property_to_text_list_for_display (GdkDisplay *display,
920 const gchar *charset;
921 gchar *source_charset;
923 g_return_val_if_fail (display == _gdk_display, 0);
926 gchar *enc_name = gdk_atom_name (encoding);
928 g_print ("gdk_text_property_to_text_list_for_display: %s %d %.20s %d\n",
929 enc_name, format, text, length);
936 if (encoding == GDK_TARGET_STRING)
937 source_charset = g_strdup ("ISO-8859-1");
938 else if (encoding == _utf8_string)
939 source_charset = g_strdup ("UTF-8");
941 source_charset = gdk_atom_name (encoding);
943 g_get_charset (&charset);
945 result = g_convert (text, length, charset, source_charset,
947 g_free (source_charset);
952 *list = g_new (gchar *, 1);
959 gdk_free_text_list (gchar **list)
961 g_return_if_fail (list != NULL);
968 make_list (const gchar *text,
973 GSList *strings = NULL;
976 const gchar *p = text;
979 GError *error = NULL;
981 while (p < text + length)
986 while (*q && q < text + length)
991 str = g_convert (p, q - p,
992 "UTF-8", "ISO-8859-1",
997 g_warning ("Error converting selection from STRING: %s",
999 g_error_free (error);
1003 str = g_strndup (p, q - p);
1007 strings = g_slist_prepend (strings, str);
1015 *list = g_new (gchar *, n_strings + 1);
1017 (*list)[n_strings] = NULL;
1024 (*list)[--i] = tmp_list->data;
1026 g_free (tmp_list->data);
1028 tmp_list = tmp_list->next;
1031 g_slist_free (strings);
1037 _gdk_win32_display_text_property_to_utf8_list (GdkDisplay *display,
1044 g_return_val_if_fail (text != NULL, 0);
1045 g_return_val_if_fail (length >= 0, 0);
1046 g_return_val_if_fail (display == _gdk_display, 0);
1048 if (encoding == GDK_TARGET_STRING)
1050 return make_list ((gchar *)text, length, TRUE, list);
1052 else if (encoding == _utf8_string)
1054 return make_list ((gchar *)text, length, FALSE, list);
1058 gchar *enc_name = gdk_atom_name (encoding);
1060 g_warning ("gdk_text_property_to_utf8_list_for_display: encoding %s not handled\n", enc_name);
1071 gdk_string_to_compound_text_for_display (GdkDisplay *display,
1078 g_return_val_if_fail (str != NULL, 0);
1079 g_return_val_if_fail (length >= 0, 0);
1080 g_return_val_if_fail (display == _gdk_display, 0);
1082 GDK_NOTE (DND, g_print ("gdk_string_to_compound_text_for_display: %.20s\n", str));
1084 /* Always fail on Win32. No COMPOUND_TEXT support. */
1087 *encoding = GDK_NONE;
1102 _gdk_win32_display_utf8_to_string_target (GdkDisplay *display,
1105 return _gdk_utf8_to_string_target_internal (str, strlen (str));
1109 gdk_utf8_to_compound_text_for_display (GdkDisplay *display,
1116 g_return_val_if_fail (str != NULL, FALSE);
1117 g_return_val_if_fail (display == _gdk_display, FALSE);
1119 GDK_NOTE (DND, g_print ("gdk_utf8_to_compound_text_for_display: %.20s\n", str));
1121 /* Always fail on Win32. No COMPOUND_TEXT support. */
1124 *encoding = GDK_NONE;
1139 gdk_free_compound_text (guchar *ctext)
1141 /* As we never generate anything claimed to be COMPOUND_TEXT, this
1142 * should never be called. Or if it is called, ctext should be the
1143 * NULL returned for conversions to COMPOUND_TEXT above.
1145 g_return_if_fail (ctext == NULL);
1148 /* This function is called from gtk_selection_add_target() and
1149 * gtk_selection_add_targets() in gtkselection.c. It is this function
1150 * that takes care of setting those clipboard formats for which we use
1151 * delayed rendering. Formats copied directly to the clipboard are
1152 * handled in gdk_property_change() in gdkproperty-win32.c.
1156 gdk_win32_selection_add_targets (GdkWindow *owner,
1162 gboolean has_image = FALSE;
1166 gchar *sel_name = gdk_atom_name (selection);
1168 g_print ("gdk_win32_selection_add_targets: %p: %s: ",
1169 owner ? GDK_WINDOW_HWND (owner) : NULL,
1173 for (i = 0; i < n_targets; i++)
1175 gchar *tgt_name = gdk_atom_name (targets[i]);
1177 g_print ("%s", tgt_name);
1179 if (i < n_targets - 1)
1185 if (selection != GDK_SELECTION_CLIPBOARD)
1190 if (GDK_WINDOW_DESTROYED (owner))
1192 hwnd = GDK_WINDOW_HWND (owner);
1195 if (!API_CALL (OpenClipboard, (hwnd)))
1198 /* We have a very simple strategy: If some kind of pixmap image
1199 * format is being added, actually advertise just PNG and DIB. PNG
1200 * is our preferred format because it can losslessly represent any
1201 * image that gdk-pixbuf formats in general can, even with alpha,
1202 * unambiguously. CF_DIB is also advertised because of the general
1203 * support for it in Windows software, but note that alpha won't be
1206 for (i = 0; !has_image && i < n_targets; ++i)
1212 for (j = 0; j < n_known_pixbuf_formats; j++)
1213 if (targets[i] == known_pixbuf_formats[j])
1217 GDK_NOTE (DND, g_print ("... SetClipboardData(PNG,NULL)\n"));
1218 SetClipboardData (_cf_png, NULL);
1220 GDK_NOTE (DND, g_print ("... SetClipboardData(CF_DIB,NULL)\n"));
1221 SetClipboardData (CF_DIB, NULL);
1228 /* If it is one of the pixmap formats, already handled or not
1231 if (j < n_known_pixbuf_formats)
1234 /* We don't bother registering and advertising clipboard formats
1235 * that are X11 specific or no non-GTK+ apps will have ever
1236 * heard of, and when there are equivalent clipboard formats
1237 * that are commonly used.
1239 if (targets[i] == _save_targets ||
1240 targets[i] == _utf8_string ||
1241 targets[i] == GDK_TARGET_STRING ||
1242 targets[i] == _compound_text ||
1243 targets[i] == _text ||
1244 targets[i] == text_plain_charset_utf_8 ||
1245 targets[i] == text_plain_charset_CP1252 ||
1246 targets[i] == text_plain)
1249 target_name = gdk_atom_name (targets[i]);
1251 if (g_str_has_prefix (target_name, "text/plain;charset="))
1253 g_free (target_name);
1257 cf = RegisterClipboardFormat (target_name);
1259 g_hash_table_replace (_format_atom_table,
1260 GINT_TO_POINTER (cf),
1263 GDK_NOTE (DND, g_print ("... SetClipboardData(%s,NULL)\n",
1264 _gdk_win32_cf_to_string (cf)));
1265 SetClipboardData (cf, NULL);
1267 g_free (target_name);
1269 API_CALL (CloseClipboard, ());
1272 /* Convert from types such as "image/jpg" or "image/png" to DIB using
1273 * gdk-pixbuf so that image copied from GTK+ apps can be pasted in
1274 * native apps like mspaint.exe
1277 _gdk_win32_selection_convert_to_dib (HGLOBAL hdata,
1281 gchar *target_name = gdk_atom_name (target);
1283 g_print ("_gdk_win32_selection_convert_to_dib: %p %s\n",
1284 hdata, target_name);
1285 g_free (target_name);
1288 if (target == _image_bmp)
1290 /* No conversion is needed, just strip the BITMAPFILEHEADER */
1292 SIZE_T size = GlobalSize (hdata) - sizeof (BITMAPFILEHEADER);
1293 guchar *ptr = GlobalLock (hdata);
1295 memmove (ptr, ptr + sizeof (BITMAPFILEHEADER), size);
1296 GlobalUnlock (hdata);
1298 if ((hdatanew = GlobalReAlloc (hdata, size, GMEM_MOVEABLE)) == NULL)
1300 WIN32_API_FAILED ("GlobalReAlloc");
1301 GlobalFree (hdata); /* The old hdata is not freed if error */
1306 g_warning ("Should not happen: We provide some image format but not CF_DIB and CF_DIB is requested.");