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, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
32 #include "gdkproperty.h"
33 #include "gdkselection.h"
34 #include "gdkdisplay.h"
35 #include "gdkprivate-win32.h"
38 /* We emulate the GDK_SELECTION window properties of windows (as used
39 * in the X11 backend) by using a hash table from window handles to
50 static GHashTable *sel_prop_table = NULL;
52 static GdkSelProp *dropfiles_prop = NULL;
54 /* We store the owner of each selection in this table. Obviously, this only
55 * is valid intra-app, and in fact it is necessary for the intra-app DND to work.
57 static GHashTable *sel_owner_table = NULL;
59 /* GdkAtoms for well-known image formats */
60 static GdkAtom *known_pixbuf_formats;
61 static int n_known_pixbuf_formats;
63 /* GdkAtoms for well-known text formats */
64 static GdkAtom text_plain;
65 static GdkAtom text_plain_charset_utf_8;
66 static GdkAtom text_plain_charset_CP1252;
69 _gdk_win32_selection_init (void)
71 GSList *pixbuf_formats;
74 sel_prop_table = g_hash_table_new (NULL, NULL);
75 sel_owner_table = g_hash_table_new (NULL, NULL);
76 _format_atom_table = g_hash_table_new (NULL, NULL);
78 pixbuf_formats = gdk_pixbuf_get_formats ();
80 n_known_pixbuf_formats = 0;
81 for (rover = pixbuf_formats; rover != NULL; rover = rover->next)
84 gdk_pixbuf_format_get_mime_types ((GdkPixbufFormat *) rover->data);
88 for (mime_type = mime_types; *mime_type != NULL; mime_type++)
89 n_known_pixbuf_formats++;
92 known_pixbuf_formats = g_new (GdkAtom, n_known_pixbuf_formats);
94 n_known_pixbuf_formats = 0;
95 for (rover = pixbuf_formats; rover != NULL; rover = rover->next)
98 gdk_pixbuf_format_get_mime_types ((GdkPixbufFormat *) rover->data);
102 for (mime_type = mime_types; *mime_type != NULL; mime_type++)
103 known_pixbuf_formats[n_known_pixbuf_formats++] = gdk_atom_intern (*mime_type, FALSE);
106 g_slist_free (pixbuf_formats);
108 text_plain = gdk_atom_intern ("text/plain", FALSE);
109 text_plain_charset_utf_8= gdk_atom_intern ("text/plain;charset=utf-8", FALSE);
110 text_plain_charset_CP1252 = gdk_atom_intern ("text/plain;charset=CP1252", FALSE);
112 g_hash_table_replace (_format_atom_table,
113 GINT_TO_POINTER (_cf_png),
116 g_hash_table_replace (_format_atom_table,
117 GINT_TO_POINTER (CF_DIB),
121 /* The specifications for COMPOUND_TEXT and STRING specify that C0 and
122 * C1 are not allowed except for \n and \t, however the X conversions
123 * routines for COMPOUND_TEXT only enforce this in one direction,
124 * causing cut-and-paste of \r and \r\n separated text to fail.
125 * This routine strips out all non-allowed C0 and C1 characters
126 * from the input string and also canonicalizes \r, and \r\n to \n
129 sanitize_utf8 (const gchar *src,
132 GString *result = g_string_sized_new (length + 1);
133 const gchar *p = src;
134 const gchar *endp = src + length;
144 g_string_append_c (result, '\n');
148 gunichar ch = g_utf8_get_char (p);
152 if (!((ch < 0x20 && ch != '\t' && ch != '\n') || (ch >= 0x7f && ch < 0xa0)))
154 buflen = g_unichar_to_utf8 (ch, buf);
155 g_string_append_len (result, buf, buflen);
158 p = g_utf8_next_char (p);
161 g_string_append_c (result, '\0');
163 return g_string_free (result, FALSE);
167 _gdk_utf8_to_string_target_internal (const gchar *str,
170 GError *error = NULL;
172 gchar *tmp_str = sanitize_utf8 (str, length);
173 gchar *result = g_convert_with_fallback (tmp_str, -1,
174 "ISO-8859-1", "UTF-8",
175 NULL, NULL, NULL, &error);
178 g_warning ("Error converting from UTF-8 to STRING: %s",
180 g_error_free (error);
188 selection_property_store (GdkWindow *owner,
196 g_return_if_fail (type != GDK_TARGET_STRING);
198 prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (owner));
204 g_hash_table_remove (sel_prop_table, GDK_WINDOW_HWND (owner));
207 prop = g_new (GdkSelProp, 1);
210 prop->length = length;
211 prop->format = format;
214 g_hash_table_insert (sel_prop_table, GDK_WINDOW_HWND (owner), prop);
218 _gdk_dropfiles_store (gchar *data)
222 g_assert (dropfiles_prop == NULL);
224 dropfiles_prop = g_new (GdkSelProp, 1);
225 dropfiles_prop->data = (guchar *) data;
226 dropfiles_prop->length = strlen (data) + 1;
227 dropfiles_prop->format = 8;
228 dropfiles_prop->type = _text_uri_list;
232 if (dropfiles_prop != NULL)
234 g_free (dropfiles_prop->data);
235 g_free (dropfiles_prop);
237 dropfiles_prop = NULL;
242 get_mapped_gdk_atom_name (GdkAtom gdk_target)
244 if (gdk_target == _image_png)
245 return g_strdup ("PNG");
247 if (gdk_target == _image_jpeg)
248 return g_strdup ("JFIF");
250 if (gdk_target == _image_gif)
251 return g_strdup ("GIF");
253 return gdk_atom_name (gdk_target);
257 _gdk_win32_display_set_selection_owner (GdkDisplay *display,
266 g_return_val_if_fail (display == _gdk_display, FALSE);
267 g_return_val_if_fail (selection != GDK_NONE, FALSE);
270 gchar *sel_name = gdk_atom_name (selection);
272 g_print ("gdk_selection_owner_set_for_display: %p %s\n",
273 (owner ? GDK_WINDOW_HWND (owner) : NULL),
278 if (selection != GDK_SELECTION_CLIPBOARD)
281 g_hash_table_insert (sel_owner_table, selection, GDK_WINDOW_HWND (owner));
283 g_hash_table_remove (sel_owner_table, selection);
287 /* Rest of this function handles the CLIPBOARD selection */
290 if (GDK_WINDOW_DESTROYED (owner))
293 hwnd = GDK_WINDOW_HWND (owner);
298 if (!API_CALL (OpenClipboard, (hwnd)))
301 _ignore_destroy_clipboard = TRUE;
302 GDK_NOTE (DND, g_print ("... EmptyClipboard()\n"));
303 if (!API_CALL (EmptyClipboard, ()))
305 _ignore_destroy_clipboard = FALSE;
306 API_CALL (CloseClipboard, ());
309 _ignore_destroy_clipboard = FALSE;
311 if (!API_CALL (CloseClipboard, ()))
316 /* Send ourselves a selection request message so that
317 * gdk_property_change will be called to store the clipboard
320 GDK_NOTE (DND, g_print ("... sending GDK_SELECTION_REQUEST to ourselves\n"));
321 tmp_event.selection.type = GDK_SELECTION_REQUEST;
322 tmp_event.selection.window = owner;
323 tmp_event.selection.send_event = FALSE;
324 tmp_event.selection.selection = selection;
325 tmp_event.selection.target = _utf8_string;
326 tmp_event.selection.property = _gdk_selection;
327 tmp_event.selection.requestor = gdk_win32_handle_table_lookup (hwnd);
328 tmp_event.selection.time = time;
330 gdk_event_put (&tmp_event);
337 _gdk_win32_display_get_selection_owner (GdkDisplay *display,
342 g_return_val_if_fail (display == _gdk_display, NULL);
343 g_return_val_if_fail (selection != GDK_NONE, NULL);
345 if (selection == GDK_SELECTION_CLIPBOARD)
347 HWND owner = GetClipboardOwner ();
352 return gdk_win32_handle_table_lookup (owner);
355 window = gdk_win32_window_lookup_for_display (display,
356 g_hash_table_lookup (sel_owner_table, selection));
359 gchar *sel_name = gdk_atom_name (selection);
361 g_print ("gdk_selection_owner_get: %s = %p\n",
363 (window ? GDK_WINDOW_HWND (window) : NULL));
371 generate_selection_notify (GdkWindow *requestor,
379 tmp_event.selection.type = GDK_SELECTION_NOTIFY;
380 tmp_event.selection.window = requestor;
381 tmp_event.selection.send_event = FALSE;
382 tmp_event.selection.selection = selection;
383 tmp_event.selection.target = target;
384 tmp_event.selection.property = property;
385 tmp_event.selection.requestor = 0;
386 tmp_event.selection.time = time;
388 gdk_event_put (&tmp_event);
392 _gdk_win32_display_convert_selection (GdkDisplay *display,
393 GdkWindow *requestor,
399 GdkAtom property = _gdk_selection;
401 g_return_if_fail (selection != GDK_NONE);
402 g_return_if_fail (requestor != NULL);
404 if (GDK_WINDOW_DESTROYED (requestor))
408 gchar *sel_name = gdk_atom_name (selection);
409 gchar *tgt_name = gdk_atom_name (target);
411 g_print ("gdk_selection_convert: %p %s %s\n",
412 GDK_WINDOW_HWND (requestor),
418 if (selection == GDK_SELECTION_CLIPBOARD && target == _targets)
422 gboolean has_text = FALSE;
423 gboolean has_png = FALSE;
424 gboolean has_bmp = FALSE;
426 if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
429 targets = g_new (GdkAtom, CountClipboardFormats ());
432 for (fmt = 0; 0 != (fmt = EnumClipboardFormats (fmt)); )
436 targets[ntargets++] = _image_png;
441 for (fmt = 0; 0 != (fmt = EnumClipboardFormats (fmt)); )
445 if (fmt == CF_UNICODETEXT || fmt == CF_TEXT)
447 /* Advertise text to GDK always as UTF8_STRING */
449 targets[ntargets++] = _utf8_string;
452 else if (fmt == _cf_png)
454 /* Already handled above */
456 else if (fmt == CF_DIB ||
459 /* Don't bother telling that a bitmap is present if there is
460 * also PNG, which is much more reliable in transferring
463 if (!has_bmp && !has_png)
464 targets[ntargets++] = _image_bmp;
467 else if (fmt == _cf_jfif)
471 targets[ntargets++] = _image_jpeg;
473 else if (fmt == _cf_gif)
478 targets[ntargets++] = _image_gif;
480 else if (GetClipboardFormatName (fmt, sFormat, 80) > 0)
482 if (strcmp (sFormat, "image/bmp") == 0 ||
483 strcmp (sFormat, "image/x-bmp") == 0 ||
484 strcmp (sFormat, "image/x-MS-bmp") == 0 ||
485 strcmp (sFormat, "image/x-icon") == 0 ||
486 strcmp (sFormat, "image/x-ico") == 0 ||
487 strcmp (sFormat, "image/x-win-bitmap") == 0)
489 /* Ignore these (from older GTK+ versions
490 * presumably), as the same image in the CF_DIB
491 * format will also be on the clipboard anyway.
495 targets[ntargets++] = gdk_atom_intern (sFormat, FALSE);
503 for (i = 0; i < ntargets; i++)
505 gchar *atom_name = gdk_atom_name (targets[i]);
507 g_print ("%s", atom_name);
509 if (i < ntargets - 1)
516 selection_property_store (requestor, GDK_SELECTION_TYPE_ATOM,
517 32, (guchar *) targets,
518 ntargets * sizeof (GdkAtom));
522 API_CALL (CloseClipboard, ());
524 else if (selection == GDK_SELECTION_CLIPBOARD && target == _utf8_string)
526 /* Converting the CLIPBOARD selection means he wants the
527 * contents of the clipboard. Get the clipboard data, and store
530 if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
533 if ((hdata = GetClipboardData (CF_UNICODETEXT)) != NULL)
535 wchar_t *ptr, *wcs, *p, *q;
539 if ((ptr = GlobalLock (hdata)) != NULL)
541 length = GlobalSize (hdata);
543 GDK_NOTE (DND, g_print ("... CF_UNICODETEXT: %ld bytes\n",
547 wcs = g_new (wchar_t, length / 2 + 1);
551 while (p < ptr + length / 2)
561 data = g_utf16_to_utf8 (wcs, wclen, NULL, NULL, NULL);
565 selection_property_store (requestor, _utf8_string, 8,
566 data, strlen (data) + 1);
567 GlobalUnlock (hdata);
573 API_CALL (CloseClipboard, ());
575 else if (selection == GDK_SELECTION_CLIPBOARD && target == _image_bmp)
577 if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
580 if ((hdata = GetClipboardData (CF_DIB)) != NULL)
582 BITMAPINFOHEADER *bi;
584 if ((bi = GlobalLock (hdata)) != NULL)
586 /* Need to add a BMP file header so gdk-pixbuf can load
589 * If the data is from Mozilla Firefox or IE7, and
590 * starts with an "old fashioned" BITMAPINFOHEADER,
591 * i.e. with biSize==40, and biCompression == BI_RGB and
592 * biBitCount==32, we assume that the "extra" byte in
593 * each pixel in fact is alpha.
595 * The gdk-pixbuf bmp loader doesn't trust 32-bit BI_RGB
596 * bitmaps to in fact have alpha, so we have to convince
597 * it by changing the bitmap header to a version 5
598 * BI_BITFIELDS one with explicit alpha mask indicated.
600 * The RGB bytes that are in bitmaps on the clipboard
601 * originating from Firefox or IE7 seem to be
602 * premultiplied with alpha. The gdk-pixbuf bmp loader
603 * of course doesn't expect that, so we have to undo the
604 * premultiplication before feeding the bitmap to the
607 * Note that for some reason the bmp loader used to want
608 * the alpha bytes in its input to actually be
609 * 255-alpha, but here we assume that this has been
610 * fixed before this is committed.
612 BITMAPFILEHEADER *bf;
614 gint data_length = GlobalSize (hdata);
616 gboolean make_dibv5 = FALSE;
618 GDK_NOTE (DND, g_print ("... CF_DIB: %d bytes\n", data_length));
620 if (bi->biSize == sizeof (BITMAPINFOHEADER) &&
622 bi->biBitCount == 32 &&
623 bi->biCompression == BI_RGB &&
625 /* Maybe check explicitly for Mozilla or IE7?
627 * If the clipboard format
628 * application/x-moz-nativeimage is present, that is
629 * a reliable indicator that the data is offered by
630 * Mozilla one would think. For IE7,
631 * UniformResourceLocatorW is presumably not that
632 * uniqie, so probably need to do some
633 * GetClipboardOwner(), GetWindowThreadProcessId(),
634 * OpenProcess(), GetModuleFileNameEx() dance to
637 (IsClipboardFormatAvailable
638 (RegisterClipboardFormat ("application/x-moz-nativeimage")) ||
639 IsClipboardFormatAvailable
640 (RegisterClipboardFormat ("UniformResourceLocatorW"))) &&
644 /* We turn the BITMAPINFOHEADER into a
645 * BITMAPV5HEADER before feeding it to gdk-pixbuf.
647 new_length = (data_length +
648 sizeof (BITMAPFILEHEADER) +
649 (sizeof (BITMAPV5HEADER) - sizeof (BITMAPINFOHEADER)));
654 new_length = data_length + sizeof (BITMAPFILEHEADER);
657 data = g_try_malloc (new_length);
661 bf = (BITMAPFILEHEADER *)data;
662 bf->bfType = 0x4d42; /* "BM" */
663 bf->bfSize = new_length;
669 BITMAPV5HEADER *bV5 = (BITMAPV5HEADER *) ((char *) data + sizeof (BITMAPFILEHEADER));
673 bV5->bV5Size = sizeof (BITMAPV5HEADER);
674 bV5->bV5Width = bi->biWidth;
675 bV5->bV5Height = bi->biHeight;
677 bV5->bV5BitCount = 32;
678 bV5->bV5Compression = BI_BITFIELDS;
679 bV5->bV5SizeImage = 4 * bV5->bV5Width * ABS (bV5->bV5Height);
680 bV5->bV5XPelsPerMeter = bi->biXPelsPerMeter;
681 bV5->bV5YPelsPerMeter = bi->biYPelsPerMeter;
683 bV5->bV5ClrImportant = 0;
684 /* Now the added mask fields */
685 bV5->bV5RedMask = 0x00ff0000;
686 bV5->bV5GreenMask = 0x0000ff00;
687 bV5->bV5BlueMask = 0x000000ff;
688 bV5->bV5AlphaMask = 0xff000000;
689 ((char *) &bV5->bV5CSType)[3] = 's';
690 ((char *) &bV5->bV5CSType)[2] = 'R';
691 ((char *) &bV5->bV5CSType)[1] = 'G';
692 ((char *) &bV5->bV5CSType)[0] = 'B';
693 /* Ignore colorspace and profile fields */
694 bV5->bV5Intent = LCS_GM_GRAPHICS;
695 bV5->bV5Reserved = 0;
697 bf->bfOffBits = (sizeof (BITMAPFILEHEADER) +
700 p = ((guchar *) data) + sizeof (BITMAPFILEHEADER) + sizeof (BITMAPV5HEADER);
701 memcpy (p, ((char *) bi) + bi->biSize,
702 data_length - sizeof (BITMAPINFOHEADER));
704 for (i = 0; i < bV5->bV5SizeImage/4; i++)
708 gdouble inverse_alpha = 255./p[3];
710 p[0] = p[0] * inverse_alpha + 0.5;
711 p[1] = p[1] * inverse_alpha + 0.5;
712 p[2] = p[2] * inverse_alpha + 0.5;
720 bf->bfOffBits = (sizeof (BITMAPFILEHEADER) +
722 bi->biClrUsed * sizeof (RGBQUAD));
724 if (bi->biCompression == BI_BITFIELDS && bi->biBitCount >= 16)
726 /* Screenshots taken with PrintScreen or
727 * Alt + PrintScreen are found on the clipboard in
728 * this format. In this case the BITMAPINFOHEADER is
729 * followed by three DWORD specifying the masks of the
730 * red green and blue components, so adjust the offset
732 bf->bfOffBits += (3 * sizeof (DWORD));
735 memcpy ((char *) data + sizeof (BITMAPFILEHEADER),
740 selection_property_store (requestor, _image_bmp, 8,
743 GlobalUnlock (hdata);
747 API_CALL (CloseClipboard, ());
749 else if (selection == GDK_SELECTION_CLIPBOARD)
751 gchar *mapped_target_name;
754 if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
757 mapped_target_name = get_mapped_gdk_atom_name (target);
759 /* Check if it's available. We could simply call
760 * GetClipboardData (RegisterClipboardFormat (targetname)), but
761 * the global custom format ID space is limited,
762 * (0xC000~0xFFFF), and we better not waste an format ID if we
763 * are just a requestor.
765 for ( ; 0 != (fmt = EnumClipboardFormats (fmt)); )
769 if (GetClipboardFormatName (fmt, sFormat, 80) > 0 &&
770 strcmp (sFormat, mapped_target_name) == 0)
772 if ((hdata = GetClipboardData (fmt)) != NULL)
774 /* Simply get it without conversion */
778 if ((ptr = GlobalLock (hdata)) != NULL)
780 length = GlobalSize (hdata);
782 GDK_NOTE (DND, g_print ("... %s: %d bytes\n", mapped_target_name, length));
784 selection_property_store (requestor, target, 8,
785 g_memdup (ptr, length), length);
786 GlobalUnlock (hdata);
792 g_free (mapped_target_name);
793 API_CALL (CloseClipboard, ());
795 else if (selection == _gdk_win32_dropfiles)
797 /* This means he wants the names of the dropped files.
798 * gdk_dropfiles_filter already has stored the text/uri-list
799 * data temporarily in dropfiles_prop.
801 if (dropfiles_prop != NULL)
803 selection_property_store
804 (requestor, dropfiles_prop->type, dropfiles_prop->format,
805 dropfiles_prop->data, dropfiles_prop->length);
806 g_free (dropfiles_prop);
807 dropfiles_prop = NULL;
813 /* Generate a selection notify message so that we actually fetch the
814 * data (if property == _gdk_selection) or indicating failure (if
815 * property == GDK_NONE).
817 generate_selection_notify (requestor, selection, target, property, time);
821 _gdk_win32_display_get_selection_property (GdkDisplay *display,
822 GdkWindow *requestor,
829 g_return_val_if_fail (requestor != NULL, 0);
830 g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
832 if (GDK_WINDOW_DESTROYED (requestor))
835 GDK_NOTE (DND, g_print ("gdk_selection_property_get: %p",
836 GDK_WINDOW_HWND (requestor)));
838 prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (requestor));
842 GDK_NOTE (DND, g_print (" (nothing)\n"));
848 *data = g_malloc (prop->length + 1);
849 (*data)[prop->length] = '\0';
850 if (prop->length > 0)
851 memmove (*data, prop->data, prop->length);
854 gchar *type_name = gdk_atom_name (prop->type);
856 g_print (" %s format:%d length:%d\n", type_name, prop->format, prop->length);
861 *ret_type = prop->type;
864 *ret_format = prop->format;
870 _gdk_selection_property_delete (GdkWindow *window)
872 GDK_NOTE (DND, g_print ("_gdk_selection_property_delete: %p (no-op)\n",
873 GDK_WINDOW_HWND (window)));
876 prop = g_hash_table_lookup (sel_prop_table, GDK_WINDOW_HWND (window));
881 g_hash_table_remove (sel_prop_table, GDK_WINDOW_HWND (window));
887 _gdk_win32_display_send_selection_notify (GdkDisplay *display,
888 GdkWindow *requestor,
894 g_return_if_fail (display == _gdk_display);
897 gchar *sel_name = gdk_atom_name (selection);
898 gchar *tgt_name = gdk_atom_name (target);
899 gchar *prop_name = gdk_atom_name (property);
901 g_print ("gdk_selection_send_notify_for_display: %p %s %s %s (no-op)\n",
902 requestor, sel_name, tgt_name, prop_name);
909 /* It's hard to say whether implementing this actually is of any use
910 * on the Win32 platform? gtk calls only
911 * gdk_text_property_to_utf8_list_for_display().
914 gdk_text_property_to_text_list_for_display (GdkDisplay *display,
922 const gchar *charset;
923 gchar *source_charset;
925 g_return_val_if_fail (display == _gdk_display, 0);
928 gchar *enc_name = gdk_atom_name (encoding);
930 g_print ("gdk_text_property_to_text_list_for_display: %s %d %.20s %d\n",
931 enc_name, format, text, length);
938 if (encoding == GDK_TARGET_STRING)
939 source_charset = g_strdup ("ISO-8859-1");
940 else if (encoding == _utf8_string)
941 source_charset = g_strdup ("UTF-8");
943 source_charset = gdk_atom_name (encoding);
945 g_get_charset (&charset);
947 result = g_convert (text, length, charset, source_charset,
949 g_free (source_charset);
954 *list = g_new (gchar *, 1);
961 gdk_free_text_list (gchar **list)
963 g_return_if_fail (list != NULL);
970 make_list (const gchar *text,
975 GSList *strings = NULL;
978 const gchar *p = text;
981 GError *error = NULL;
983 while (p < text + length)
988 while (*q && q < text + length)
993 str = g_convert (p, q - p,
994 "UTF-8", "ISO-8859-1",
999 g_warning ("Error converting selection from STRING: %s",
1001 g_error_free (error);
1005 str = g_strndup (p, q - p);
1009 strings = g_slist_prepend (strings, str);
1017 *list = g_new (gchar *, n_strings + 1);
1019 (*list)[n_strings] = NULL;
1026 (*list)[--i] = tmp_list->data;
1028 g_free (tmp_list->data);
1030 tmp_list = tmp_list->next;
1033 g_slist_free (strings);
1039 _gdk_win32_display_text_property_to_utf8_list (GdkDisplay *display,
1046 g_return_val_if_fail (text != NULL, 0);
1047 g_return_val_if_fail (length >= 0, 0);
1048 g_return_val_if_fail (display == _gdk_display, 0);
1050 if (encoding == GDK_TARGET_STRING)
1052 return make_list ((gchar *)text, length, TRUE, list);
1054 else if (encoding == _utf8_string)
1056 return make_list ((gchar *)text, length, FALSE, list);
1060 gchar *enc_name = gdk_atom_name (encoding);
1062 g_warning ("gdk_text_property_to_utf8_list_for_display: encoding %s not handled\n", enc_name);
1073 gdk_string_to_compound_text_for_display (GdkDisplay *display,
1080 g_return_val_if_fail (str != NULL, 0);
1081 g_return_val_if_fail (length >= 0, 0);
1082 g_return_val_if_fail (display == _gdk_display, 0);
1084 GDK_NOTE (DND, g_print ("gdk_string_to_compound_text_for_display: %.20s\n", str));
1086 /* Always fail on Win32. No COMPOUND_TEXT support. */
1089 *encoding = GDK_NONE;
1104 _gdk_win32_display_utf8_to_string_target (GdkDisplay *display,
1107 return _gdk_utf8_to_string_target_internal (str, strlen (str));
1111 gdk_utf8_to_compound_text_for_display (GdkDisplay *display,
1118 g_return_val_if_fail (str != NULL, FALSE);
1119 g_return_val_if_fail (display == _gdk_display, FALSE);
1121 GDK_NOTE (DND, g_print ("gdk_utf8_to_compound_text_for_display: %.20s\n", str));
1123 /* Always fail on Win32. No COMPOUND_TEXT support. */
1126 *encoding = GDK_NONE;
1141 gdk_free_compound_text (guchar *ctext)
1143 /* As we never generate anything claimed to be COMPOUND_TEXT, this
1144 * should never be called. Or if it is called, ctext should be the
1145 * NULL returned for conversions to COMPOUND_TEXT above.
1147 g_return_if_fail (ctext == NULL);
1150 /* This function is called from gtk_selection_add_target() and
1151 * gtk_selection_add_targets() in gtkselection.c. It is this function
1152 * that takes care of setting those clipboard formats for which we use
1153 * delayed rendering. Formats copied directly to the clipboard are
1154 * handled in gdk_property_change() in gdkproperty-win32.c.
1158 gdk_win32_selection_add_targets (GdkWindow *owner,
1164 gboolean has_image = FALSE;
1168 gchar *sel_name = gdk_atom_name (selection);
1170 g_print ("gdk_win32_selection_add_targets: %p: %s: ",
1171 owner ? GDK_WINDOW_HWND (owner) : NULL,
1175 for (i = 0; i < n_targets; i++)
1177 gchar *tgt_name = gdk_atom_name (targets[i]);
1179 g_print ("%s", tgt_name);
1181 if (i < n_targets - 1)
1187 if (selection != GDK_SELECTION_CLIPBOARD)
1192 if (GDK_WINDOW_DESTROYED (owner))
1194 hwnd = GDK_WINDOW_HWND (owner);
1197 if (!API_CALL (OpenClipboard, (hwnd)))
1200 /* We have a very simple strategy: If some kind of pixmap image
1201 * format is being added, actually advertise just PNG and DIB. PNG
1202 * is our preferred format because it can losslessly represent any
1203 * image that gdk-pixbuf formats in general can, even with alpha,
1204 * unambiguously. CF_DIB is also advertised because of the general
1205 * support for it in Windows software, but note that alpha won't be
1208 for (i = 0; !has_image && i < n_targets; ++i)
1214 for (j = 0; j < n_known_pixbuf_formats; j++)
1215 if (targets[i] == known_pixbuf_formats[j])
1219 GDK_NOTE (DND, g_print ("... SetClipboardData(PNG,NULL)\n"));
1220 SetClipboardData (_cf_png, NULL);
1222 GDK_NOTE (DND, g_print ("... SetClipboardData(CF_DIB,NULL)\n"));
1223 SetClipboardData (CF_DIB, NULL);
1230 /* If it is one of the pixmap formats, already handled or not
1233 if (j < n_known_pixbuf_formats)
1236 /* We don't bother registering and advertising clipboard formats
1237 * that are X11 specific or no non-GTK+ apps will have ever
1238 * heard of, and when there are equivalent clipboard formats
1239 * that are commonly used.
1241 if (targets[i] == _save_targets ||
1242 targets[i] == _utf8_string ||
1243 targets[i] == GDK_TARGET_STRING ||
1244 targets[i] == _compound_text ||
1245 targets[i] == _text ||
1246 targets[i] == text_plain_charset_utf_8 ||
1247 targets[i] == text_plain_charset_CP1252 ||
1248 targets[i] == text_plain)
1251 target_name = gdk_atom_name (targets[i]);
1253 if (g_str_has_prefix (target_name, "text/plain;charset="))
1255 g_free (target_name);
1259 cf = RegisterClipboardFormat (target_name);
1261 g_hash_table_replace (_format_atom_table,
1262 GINT_TO_POINTER (cf),
1265 GDK_NOTE (DND, g_print ("... SetClipboardData(%s,NULL)\n",
1266 _gdk_win32_cf_to_string (cf)));
1267 SetClipboardData (cf, NULL);
1269 g_free (target_name);
1271 API_CALL (CloseClipboard, ());
1274 /* Convert from types such as "image/jpg" or "image/png" to DIB using
1275 * gdk-pixbuf so that image copied from GTK+ apps can be pasted in
1276 * native apps like mspaint.exe
1279 _gdk_win32_selection_convert_to_dib (HGLOBAL hdata,
1283 gchar *target_name = gdk_atom_name (target);
1285 g_print ("_gdk_win32_selection_convert_to_dib: %p %s\n",
1286 hdata, target_name);
1287 g_free (target_name);
1290 if (target == _image_bmp)
1292 /* No conversion is needed, just strip the BITMAPFILEHEADER */
1294 SIZE_T size = GlobalSize (hdata) - sizeof (BITMAPFILEHEADER);
1295 guchar *ptr = GlobalLock (hdata);
1297 memmove (ptr, ptr + sizeof (BITMAPFILEHEADER), size);
1298 GlobalUnlock (hdata);
1300 if ((hdatanew = GlobalReAlloc (hdata, size, GMEM_MOVEABLE)) == NULL)
1302 WIN32_API_FAILED ("GlobalReAlloc");
1303 GlobalFree (hdata); /* The old hdata is not freed if error */
1308 g_warning ("Should not happen: We provide some image format but not CF_DIB and CF_DIB is requested.");