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 "gdkprivate-win32.h"
37 gdk_atom_intern (const gchar *atom_name,
42 static GHashTable *atom_hash = NULL;
45 atom_hash = g_hash_table_new (g_str_hash, g_str_equal);
47 retval = g_hash_table_lookup (atom_hash, atom_name);
50 if (strcmp (atom_name, "PRIMARY") == 0)
51 retval = GDK_SELECTION_PRIMARY;
52 else if (strcmp (atom_name, "SECONDARY") == 0)
53 retval = GDK_SELECTION_SECONDARY;
54 else if (strcmp (atom_name, "CLIPBOARD") == 0)
55 retval = GDK_SELECTION_CLIPBOARD;
56 else if (strcmp (atom_name, "ATOM") == 0)
57 retval = GDK_SELECTION_TYPE_ATOM;
58 else if (strcmp (atom_name, "BITMAP") == 0)
59 retval = GDK_SELECTION_TYPE_BITMAP;
60 else if (strcmp (atom_name, "COLORMAP") == 0)
61 retval = GDK_SELECTION_TYPE_COLORMAP;
62 else if (strcmp (atom_name, "DRAWABLE") == 0)
63 retval = GDK_SELECTION_TYPE_DRAWABLE;
64 else if (strcmp (atom_name, "INTEGER") == 0)
65 retval = GDK_SELECTION_TYPE_INTEGER;
66 else if (strcmp (atom_name, "PIXMAP") == 0)
67 retval = GDK_SELECTION_TYPE_PIXMAP;
68 else if (strcmp (atom_name, "WINDOW") == 0)
69 retval = GDK_SELECTION_TYPE_WINDOW;
70 else if (strcmp (atom_name, "STRING") == 0)
71 retval = GDK_SELECTION_TYPE_STRING;
74 win32_atom = GlobalAddAtom (atom_name);
75 retval = GUINT_TO_POINTER ((guint) win32_atom);
77 g_hash_table_insert (atom_hash,
86 gdk_atom_name (GdkAtom atom)
91 if (GDK_SELECTION_PRIMARY == atom) return g_strdup ("PRIMARY");
92 else if (GDK_SELECTION_SECONDARY == atom) return g_strdup ("SECONDARY");
93 else if (GDK_SELECTION_CLIPBOARD == atom) return g_strdup ("CLIPBOARD");
94 else if (GDK_SELECTION_TYPE_ATOM == atom) return g_strdup ("ATOM");
95 else if (GDK_SELECTION_TYPE_BITMAP == atom) return g_strdup ("BITMAP");
96 else if (GDK_SELECTION_TYPE_COLORMAP == atom) return g_strdup ("COLORMAP");
97 else if (GDK_SELECTION_TYPE_DRAWABLE == atom) return g_strdup ("DRAWABLE");
98 else if (GDK_SELECTION_TYPE_INTEGER == atom) return g_strdup ("INTEGER");
99 else if (GDK_SELECTION_TYPE_PIXMAP == atom) return g_strdup ("PIXMAP");
100 else if (GDK_SELECTION_TYPE_WINDOW == atom) return g_strdup ("WINDOW");
101 else if (GDK_SELECTION_TYPE_STRING == atom) return g_strdup ("STRING");
103 win32_atom = GPOINTER_TO_UINT (atom);
105 if (win32_atom < 0xC000)
106 return g_strdup_printf ("#%p", atom);
107 else if (GlobalGetAtomName (win32_atom, name, sizeof (name)) == 0)
109 return g_strdup (name);
113 gdk_property_get (GdkWindow *window,
119 GdkAtom *actual_property_type,
120 gint *actual_format_type,
124 g_return_val_if_fail (window != NULL, FALSE);
125 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
127 if (GDK_WINDOW_DESTROYED (window))
130 g_warning ("gdk_property_get: Not implemented");
136 find_common_locale (const guchar *data,
147 #define ENTRY(lang, sublang) \
148 { MAKELCID (MAKELANGID (LANG_##lang, SUBLANG_##sublang), SORT_DEFAULT), 0 }
149 ENTRY (ENGLISH, DEFAULT),
150 ENTRY (POLISH, DEFAULT),
151 ENTRY (CZECH, DEFAULT),
152 ENTRY (LITHUANIAN, DEFAULT),
153 ENTRY (RUSSIAN, DEFAULT),
154 ENTRY (GREEK, DEFAULT),
155 ENTRY (TURKISH, DEFAULT),
156 ENTRY (HEBREW, DEFAULT),
157 ENTRY (ARABIC, DEFAULT),
158 ENTRY (THAI, DEFAULT),
159 ENTRY (JAPANESE, DEFAULT),
160 ENTRY (CHINESE, CHINESE_SIMPLIFIED),
161 ENTRY (CHINESE, CHINESE_TRADITIONAL),
162 ENTRY (KOREAN, DEFAULT),
166 static gboolean been_here = FALSE;
170 /* For each installed locale: Get the locale's default code page,
171 * and store the list of locales and code pages.
176 for (i = 0; i < G_N_ELEMENTS (locales); i++)
177 if (IsValidLocale (locales[i].lcid, LCID_INSTALLED))
180 if (GetLocaleInfo (locales[i].lcid, LOCALE_IDEFAULTANSICODEPAGE,
184 locales[i].cp = atoi (buf);
185 GDK_NOTE (DND, (GetLocaleInfo (locales[i].lcid,
187 name, sizeof (name)),
188 g_print ("locale %#lx: %s: CP%d\n",
189 (gulong) locales[i].lcid, name,
195 /* Allocate bufp big enough to store data in any code page. Two
196 * bytes for each Unicode char should be enough, Windows code pages
197 * are either single- or double-byte.
199 *bufp = g_malloc ((nchars+1) * 2);
200 wcs = g_new (wchar_t, nchars+1);
202 /* Convert to Windows wide chars into temp buf */
203 _gdk_utf8_to_ucs2 (wcs, data, nelements, nchars);
206 /* For each code page that is the default for an installed locale: */
207 for (i = 0; i < G_N_ELEMENTS (locales); i++)
212 if (locales[i].cp == 0)
215 /* Convert to that code page into bufp */
217 nbytes = WideCharToMultiByte (locales[i].cp, 0, wcs, -1,
219 NULL, &used_default);
223 /* This locale is good for the string */
225 *lcidp = locales[i].lcid;
238 gdk_property_change (GdkWindow *window,
246 HGLOBAL hdata, hlcid, hutf8;
251 gint i, size, nchars;
252 gchar *prop_name, *type_name;
253 guchar *ucptr, *buf = NULL;
255 enum { PLAIN_ASCII, UNICODE_TEXT, SINGLE_LOCALE, RICH_TEXT } method;
258 g_return_if_fail (window != NULL);
259 g_return_if_fail (GDK_IS_WINDOW (window));
261 if (GDK_WINDOW_DESTROYED (window))
265 (prop_name = gdk_atom_name (property),
266 type_name = gdk_atom_name (type),
267 g_print ("gdk_property_change: %#x %#x (%s) %#x (%s) %s %d*%d bytes %.10s\n",
268 (guint) GDK_WINDOW_HWND (window),
269 (guint) property, prop_name,
270 (guint) type, type_name,
271 (mode == GDK_PROP_MODE_REPLACE ? "REPLACE" :
272 (mode == GDK_PROP_MODE_PREPEND ? "PREPEND" :
273 (mode == GDK_PROP_MODE_APPEND ? "APPEND" :
275 format, nelements, data),
277 g_free (type_name)));
279 if (property == _gdk_selection_property
280 && type == GDK_TARGET_STRING
282 && mode == GDK_PROP_MODE_REPLACE)
284 if (!OpenClipboard (GDK_WINDOW_HWND (window)))
286 WIN32_API_FAILED ("OpenClipboard");
290 /* Check if only ASCII */
291 for (i = 0; i < nelements; i++)
298 nchars = g_utf8_strlen (data, nelements);
300 GDK_NOTE (DND, g_print ("...nchars:%d\n", nchars));
304 /* If only ASCII, use CF_TEXT and the data as such. */
305 method = PLAIN_ASCII;
307 for (i = 0; i < nelements; i++)
311 GDK_NOTE (DND, g_print ("...as text: %.40s\n", data));
313 else if (IS_WIN_NT ())
315 /* On NT, use CF_UNICODETEXT if any non-ASCII char present */
316 method = UNICODE_TEXT;
317 size = (nchars + 1) * 2;
318 GDK_NOTE (DND, g_print ("...as Unicode\n"));
320 else if (find_common_locale (data, nelements, nchars, &lcid, &buf, &size))
322 /* On Win9x, if all chars are in the default code page of
323 * some installed locale, use CF_TEXT and CF_LOCALE.
325 method = SINGLE_LOCALE;
326 GDK_NOTE (DND, g_print ("...as text in locale %#lx %d bytes\n",
327 (gulong) lcid, size));
331 /* On Win9x, otherwise use RTF */
333 const guchar *p = data;
336 rtf = g_string_new ("{\\rtf1\\uc0 ");
338 while (p < data + nelements)
344 rtf = g_string_append_c (rtf, '\\');
345 rtf = g_string_append_c (rtf, *p);
350 rtf = g_string_append_c (rtf, *p);
358 rtf = g_string_append (rtf, "\\uNNNNN ");
359 rtf->len -= 6; /* five digits and a space */
360 q = rtf->str + rtf->len;
361 n = sprintf (q, "%d ", g_utf8_get_char (p));
365 p = g_utf8_next_char (p);
368 rtf = g_string_append (rtf, "}");
370 GDK_NOTE (DND, g_print ("...as RTF: %.40s\n", rtf->str));
373 if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
375 WIN32_API_FAILED ("GlobalAlloc");
376 if (!CloseClipboard ())
377 WIN32_API_FAILED ("CloseClipboard");
381 g_string_free (rtf, TRUE);
385 ucptr = GlobalLock (hdata);
391 for (i = 0; i < nelements; i++)
402 wcptr = (wchar_t *) ucptr;
403 if (_gdk_utf8_to_ucs2 (wcptr, data, nelements, nchars) == -1)
404 g_warning ("_gdk_utf8_to_ucs2() failed");
410 memmove (ucptr, buf, size);
413 /* Set the CF_LOCALE clipboard data, too */
414 if (!(hlcid = GlobalAlloc (GMEM_MOVEABLE, sizeof (LCID))))
415 WIN32_API_FAILED ("GlobalAlloc"), ok = FALSE;
418 lcidptr = GlobalLock (hlcid);
420 GlobalUnlock (hlcid);
421 if (!SetClipboardData (CF_LOCALE, hlcid))
422 WIN32_API_FAILED ("SetClipboardData (CF_LOCALE)"), ok = FALSE;
428 memmove (ucptr, rtf->str, size);
429 g_string_free (rtf, TRUE);
431 /* Set the UTF8_STRING clipboard data, too, for other
432 * GTK+ apps to use (won't bother reading RTF).
434 if (!(hutf8 = GlobalAlloc (GMEM_MOVEABLE, nelements)))
435 WIN32_API_FAILED ("GlobalAlloc");
438 guchar *utf8ptr = GlobalLock (hutf8);
439 memmove (utf8ptr, data, nelements);
440 GlobalUnlock (hutf8);
441 if (!SetClipboardData (cf_utf8_string, hutf8))
442 WIN32_API_FAILED ("SetClipboardData (UTF8_STRING)");
447 g_assert_not_reached ();
450 GlobalUnlock (hdata);
451 if (ok && !SetClipboardData (cf, hdata))
452 WIN32_API_FAILED ("SetClipboardData"), ok = FALSE;
454 if (!CloseClipboard ())
455 WIN32_API_FAILED ("CloseClipboard");
458 g_warning ("gdk_property_change: General case not implemented");
462 gdk_property_delete (GdkWindow *window,
467 g_return_if_fail (window != NULL);
468 g_return_if_fail (GDK_IS_WINDOW (window));
471 (prop_name = gdk_atom_name (property),
472 g_print ("gdk_property_delete: %#x %#x (%s)\n",
473 (window ? (guint) GDK_WINDOW_HWND (window) : 0),
474 (guint) property, prop_name),
475 g_free (prop_name)));
477 if (property == _gdk_selection_property)
478 _gdk_selection_property_delete (window);
480 g_warning ("gdk_property_delete: General case not implemented");
484 gdk_setting_get (const gchar *name,
488 * XXX : if these values get changed through the Windoze UI the
489 * respective gdk_events are not generated yet.
491 if (strcmp ("double-click-timeout", name) == 0)
493 g_value_set_int (value, GetDoubleClickTime ());
496 else if (strcmp ("drag-threshold", name) == 0)
498 g_value_set_int (value, MAX(GetSystemMetrics (SM_CXDRAG), GetSystemMetrics (SM_CYDRAG)));