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 "gdkscreen.h"
33 #include "gdkproperty.h"
34 #include "gdkselection.h"
35 #include "gdkprivate-win32.h"
38 gdk_atom_intern (const gchar *atom_name,
43 static GHashTable *atom_hash = NULL;
46 atom_hash = g_hash_table_new (g_str_hash, g_str_equal);
48 retval = g_hash_table_lookup (atom_hash, atom_name);
51 if (strcmp (atom_name, "PRIMARY") == 0)
52 retval = GDK_SELECTION_PRIMARY;
53 else if (strcmp (atom_name, "SECONDARY") == 0)
54 retval = GDK_SELECTION_SECONDARY;
55 else if (strcmp (atom_name, "CLIPBOARD") == 0)
56 retval = GDK_SELECTION_CLIPBOARD;
57 else if (strcmp (atom_name, "ATOM") == 0)
58 retval = GDK_SELECTION_TYPE_ATOM;
59 else if (strcmp (atom_name, "BITMAP") == 0)
60 retval = GDK_SELECTION_TYPE_BITMAP;
61 else if (strcmp (atom_name, "COLORMAP") == 0)
62 retval = GDK_SELECTION_TYPE_COLORMAP;
63 else if (strcmp (atom_name, "DRAWABLE") == 0)
64 retval = GDK_SELECTION_TYPE_DRAWABLE;
65 else if (strcmp (atom_name, "INTEGER") == 0)
66 retval = GDK_SELECTION_TYPE_INTEGER;
67 else if (strcmp (atom_name, "PIXMAP") == 0)
68 retval = GDK_SELECTION_TYPE_PIXMAP;
69 else if (strcmp (atom_name, "WINDOW") == 0)
70 retval = GDK_SELECTION_TYPE_WINDOW;
71 else if (strcmp (atom_name, "STRING") == 0)
72 retval = GDK_SELECTION_TYPE_STRING;
75 win32_atom = GlobalAddAtom (atom_name);
76 retval = GUINT_TO_POINTER ((guint) win32_atom);
78 g_hash_table_insert (atom_hash,
87 gdk_atom_name (GdkAtom atom)
92 if (GDK_SELECTION_PRIMARY == atom) return g_strdup ("PRIMARY");
93 else if (GDK_SELECTION_SECONDARY == atom) return g_strdup ("SECONDARY");
94 else if (GDK_SELECTION_CLIPBOARD == atom) return g_strdup ("CLIPBOARD");
95 else if (GDK_SELECTION_TYPE_ATOM == atom) return g_strdup ("ATOM");
96 else if (GDK_SELECTION_TYPE_BITMAP == atom) return g_strdup ("BITMAP");
97 else if (GDK_SELECTION_TYPE_COLORMAP == atom) return g_strdup ("COLORMAP");
98 else if (GDK_SELECTION_TYPE_DRAWABLE == atom) return g_strdup ("DRAWABLE");
99 else if (GDK_SELECTION_TYPE_INTEGER == atom) return g_strdup ("INTEGER");
100 else if (GDK_SELECTION_TYPE_PIXMAP == atom) return g_strdup ("PIXMAP");
101 else if (GDK_SELECTION_TYPE_WINDOW == atom) return g_strdup ("WINDOW");
102 else if (GDK_SELECTION_TYPE_STRING == atom) return g_strdup ("STRING");
104 win32_atom = GPOINTER_TO_UINT (atom);
106 if (win32_atom < 0xC000)
107 return g_strdup_printf ("#%p", atom);
108 else if (GlobalGetAtomName (win32_atom, name, sizeof (name)) == 0)
110 return g_strdup (name);
114 gdk_property_get (GdkWindow *window,
120 GdkAtom *actual_property_type,
121 gint *actual_format_type,
125 g_return_val_if_fail (window != NULL, FALSE);
126 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
128 if (GDK_WINDOW_DESTROYED (window))
131 g_warning ("gdk_property_get: Not implemented");
137 find_common_locale (const guchar *data,
148 #define ENTRY(lang, sublang) \
149 { MAKELCID (MAKELANGID (LANG_##lang, SUBLANG_##sublang), SORT_DEFAULT), 0 }
150 ENTRY (ENGLISH, DEFAULT),
151 ENTRY (POLISH, DEFAULT),
152 ENTRY (CZECH, DEFAULT),
153 ENTRY (LITHUANIAN, DEFAULT),
154 ENTRY (RUSSIAN, DEFAULT),
155 ENTRY (GREEK, DEFAULT),
156 ENTRY (TURKISH, DEFAULT),
157 ENTRY (HEBREW, DEFAULT),
158 ENTRY (ARABIC, DEFAULT),
159 ENTRY (THAI, DEFAULT),
160 ENTRY (JAPANESE, DEFAULT),
161 ENTRY (CHINESE, CHINESE_SIMPLIFIED),
162 ENTRY (CHINESE, CHINESE_TRADITIONAL),
163 ENTRY (KOREAN, DEFAULT),
167 static gboolean been_here = FALSE;
171 /* For each installed locale: Get the locale's default code page,
172 * and store the list of locales and code pages.
177 for (i = 0; i < G_N_ELEMENTS (locales); i++)
178 if (IsValidLocale (locales[i].lcid, LCID_INSTALLED))
181 if (GetLocaleInfo (locales[i].lcid, LOCALE_IDEFAULTANSICODEPAGE,
185 locales[i].cp = atoi (buf);
186 GDK_NOTE (DND, (GetLocaleInfo (locales[i].lcid,
188 name, sizeof (name)),
189 g_print ("locale %#lx: %s: CP%d\n",
190 (gulong) locales[i].lcid, name,
196 /* Allocate bufp big enough to store data in any code page. Two
197 * bytes for each Unicode char should be enough, Windows code pages
198 * are either single- or double-byte.
200 *bufp = g_malloc ((nchars+1) * 2);
201 wcs = g_new (wchar_t, nchars+1);
203 /* Convert to Windows wide chars into temp buf */
204 _gdk_utf8_to_ucs2 (wcs, data, nelements, nchars);
207 /* For each code page that is the default for an installed locale: */
208 for (i = 0; i < G_N_ELEMENTS (locales); i++)
213 if (locales[i].cp == 0)
216 /* Convert to that code page into bufp */
218 nbytes = WideCharToMultiByte (locales[i].cp, 0, wcs, -1,
220 NULL, &used_default);
224 /* This locale is good for the string */
226 *lcidp = locales[i].lcid;
239 gdk_property_change (GdkWindow *window,
247 HGLOBAL hdata, hlcid, hutf8;
252 gint i, size, nchars;
253 gchar *prop_name, *type_name;
254 guchar *ucptr, *buf = NULL;
256 enum { PLAIN_ASCII, UNICODE_TEXT, SINGLE_LOCALE, RICH_TEXT } method;
259 g_return_if_fail (window != NULL);
260 g_return_if_fail (GDK_IS_WINDOW (window));
262 if (GDK_WINDOW_DESTROYED (window))
266 (prop_name = gdk_atom_name (property),
267 type_name = gdk_atom_name (type),
268 g_print ("gdk_property_change: %#x %#x (%s) %#x (%s) %s %d*%d bytes %.10s\n",
269 (guint) GDK_WINDOW_HWND (window),
270 (guint) property, prop_name,
271 (guint) type, type_name,
272 (mode == GDK_PROP_MODE_REPLACE ? "REPLACE" :
273 (mode == GDK_PROP_MODE_PREPEND ? "PREPEND" :
274 (mode == GDK_PROP_MODE_APPEND ? "APPEND" :
276 format, nelements, data),
278 g_free (type_name)));
280 if (property == _gdk_selection_property
281 && type == GDK_TARGET_STRING
283 && mode == GDK_PROP_MODE_REPLACE)
285 if (!OpenClipboard (GDK_WINDOW_HWND (window)))
287 WIN32_API_FAILED ("OpenClipboard");
291 /* Check if only ASCII */
292 for (i = 0; i < nelements; i++)
299 nchars = g_utf8_strlen (data, nelements);
301 GDK_NOTE (DND, g_print ("...nchars:%d\n", nchars));
305 /* If only ASCII, use CF_TEXT and the data as such. */
306 method = PLAIN_ASCII;
308 for (i = 0; i < nelements; i++)
312 GDK_NOTE (DND, g_print ("...as text: %.40s\n", data));
314 else if (IS_WIN_NT ())
316 /* On NT, use CF_UNICODETEXT if any non-ASCII char present */
317 method = UNICODE_TEXT;
318 size = (nchars + 1) * 2;
319 GDK_NOTE (DND, g_print ("...as Unicode\n"));
321 else if (find_common_locale (data, nelements, nchars, &lcid, &buf, &size))
323 /* On Win9x, if all chars are in the default code page of
324 * some installed locale, use CF_TEXT and CF_LOCALE.
326 method = SINGLE_LOCALE;
327 GDK_NOTE (DND, g_print ("...as text in locale %#lx %d bytes\n",
328 (gulong) lcid, size));
332 /* On Win9x, otherwise use RTF */
334 const guchar *p = data;
337 rtf = g_string_new ("{\\rtf1\\uc0 ");
339 while (p < data + nelements)
345 rtf = g_string_append_c (rtf, '\\');
346 rtf = g_string_append_c (rtf, *p);
351 rtf = g_string_append_c (rtf, *p);
359 rtf = g_string_append (rtf, "\\uNNNNN ");
360 rtf->len -= 6; /* five digits and a space */
361 q = rtf->str + rtf->len;
362 n = sprintf (q, "%d ", g_utf8_get_char (p));
366 p = g_utf8_next_char (p);
369 rtf = g_string_append (rtf, "}");
371 GDK_NOTE (DND, g_print ("...as RTF: %.40s\n", rtf->str));
374 if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
376 WIN32_API_FAILED ("GlobalAlloc");
377 if (!CloseClipboard ())
378 WIN32_API_FAILED ("CloseClipboard");
382 g_string_free (rtf, TRUE);
386 ucptr = GlobalLock (hdata);
392 for (i = 0; i < nelements; i++)
403 wcptr = (wchar_t *) ucptr;
404 if (_gdk_utf8_to_ucs2 (wcptr, data, nelements, nchars) == -1)
405 g_warning ("_gdk_utf8_to_ucs2() failed");
411 memmove (ucptr, buf, size);
414 /* Set the CF_LOCALE clipboard data, too */
415 if (!(hlcid = GlobalAlloc (GMEM_MOVEABLE, sizeof (LCID))))
416 WIN32_API_FAILED ("GlobalAlloc"), ok = FALSE;
419 lcidptr = GlobalLock (hlcid);
421 GlobalUnlock (hlcid);
422 if (!SetClipboardData (CF_LOCALE, hlcid))
423 WIN32_API_FAILED ("SetClipboardData (CF_LOCALE)"), ok = FALSE;
429 memmove (ucptr, rtf->str, size);
430 g_string_free (rtf, TRUE);
432 /* Set the UTF8_STRING clipboard data, too, for other
433 * GTK+ apps to use (won't bother reading RTF).
435 if (!(hutf8 = GlobalAlloc (GMEM_MOVEABLE, nelements)))
436 WIN32_API_FAILED ("GlobalAlloc");
439 guchar *utf8ptr = GlobalLock (hutf8);
440 memmove (utf8ptr, data, nelements);
441 GlobalUnlock (hutf8);
442 if (!SetClipboardData (_cf_utf8_string, hutf8))
443 WIN32_API_FAILED ("SetClipboardData (UTF8_STRING)");
448 g_assert_not_reached ();
451 GlobalUnlock (hdata);
452 if (ok && !SetClipboardData (cf, hdata))
453 WIN32_API_FAILED ("SetClipboardData"), ok = FALSE;
455 if (!CloseClipboard ())
456 WIN32_API_FAILED ("CloseClipboard");
459 g_warning ("gdk_property_change: General case not implemented");
463 gdk_property_delete (GdkWindow *window,
468 g_return_if_fail (window != NULL);
469 g_return_if_fail (GDK_IS_WINDOW (window));
472 (prop_name = gdk_atom_name (property),
473 g_print ("gdk_property_delete: %#x %#x (%s)\n",
474 (window ? (guint) GDK_WINDOW_HWND (window) : 0),
475 (guint) property, prop_name),
476 g_free (prop_name)));
478 if (property == _gdk_selection_property)
479 _gdk_selection_property_delete (window);
481 g_warning ("gdk_property_delete: General case not implemented");
485 gdk_screen_get_setting (GdkScreen *screen,
489 g_return_val_if_fail (screen == gdk_screen_get_default (), FALSE);
492 * XXX : if these values get changed through the Windoze UI the
493 * respective gdk_events are not generated yet.
495 if (strcmp ("double-click-timeout", name) == 0)
497 g_value_set_int (value, GetDoubleClickTime ());
500 else if (strcmp ("drag-threshold", name) == 0)
502 g_value_set_int (value, MAX(GetSystemMetrics (SM_CXDRAG), GetSystemMetrics (SM_CYDRAG)));