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/.
31 #include <glib/gprintf.h>
33 #include "gdkscreen.h"
34 #include "gdkproperty.h"
35 #include "gdkselection.h"
36 #include "gdkprivate-win32.h"
39 gdk_atom_intern (const gchar *atom_name,
44 static GHashTable *atom_hash = NULL;
47 atom_hash = g_hash_table_new (g_str_hash, g_str_equal);
49 retval = g_hash_table_lookup (atom_hash, atom_name);
52 if (strcmp (atom_name, "PRIMARY") == 0)
53 retval = GDK_SELECTION_PRIMARY;
54 else if (strcmp (atom_name, "SECONDARY") == 0)
55 retval = GDK_SELECTION_SECONDARY;
56 else if (strcmp (atom_name, "CLIPBOARD") == 0)
57 retval = GDK_SELECTION_CLIPBOARD;
58 else if (strcmp (atom_name, "ATOM") == 0)
59 retval = GDK_SELECTION_TYPE_ATOM;
60 else if (strcmp (atom_name, "BITMAP") == 0)
61 retval = GDK_SELECTION_TYPE_BITMAP;
62 else if (strcmp (atom_name, "COLORMAP") == 0)
63 retval = GDK_SELECTION_TYPE_COLORMAP;
64 else if (strcmp (atom_name, "DRAWABLE") == 0)
65 retval = GDK_SELECTION_TYPE_DRAWABLE;
66 else if (strcmp (atom_name, "INTEGER") == 0)
67 retval = GDK_SELECTION_TYPE_INTEGER;
68 else if (strcmp (atom_name, "PIXMAP") == 0)
69 retval = GDK_SELECTION_TYPE_PIXMAP;
70 else if (strcmp (atom_name, "WINDOW") == 0)
71 retval = GDK_SELECTION_TYPE_WINDOW;
72 else if (strcmp (atom_name, "STRING") == 0)
73 retval = GDK_SELECTION_TYPE_STRING;
76 win32_atom = GlobalAddAtom (atom_name);
77 retval = GUINT_TO_POINTER ((guint) win32_atom);
79 g_hash_table_insert (atom_hash,
88 gdk_atom_name (GdkAtom atom)
93 if (GDK_SELECTION_PRIMARY == atom) return g_strdup ("PRIMARY");
94 else if (GDK_SELECTION_SECONDARY == atom) return g_strdup ("SECONDARY");
95 else if (GDK_SELECTION_CLIPBOARD == atom) return g_strdup ("CLIPBOARD");
96 else if (GDK_SELECTION_TYPE_ATOM == atom) return g_strdup ("ATOM");
97 else if (GDK_SELECTION_TYPE_BITMAP == atom) return g_strdup ("BITMAP");
98 else if (GDK_SELECTION_TYPE_COLORMAP == atom) return g_strdup ("COLORMAP");
99 else if (GDK_SELECTION_TYPE_DRAWABLE == atom) return g_strdup ("DRAWABLE");
100 else if (GDK_SELECTION_TYPE_INTEGER == atom) return g_strdup ("INTEGER");
101 else if (GDK_SELECTION_TYPE_PIXMAP == atom) return g_strdup ("PIXMAP");
102 else if (GDK_SELECTION_TYPE_WINDOW == atom) return g_strdup ("WINDOW");
103 else if (GDK_SELECTION_TYPE_STRING == atom) return g_strdup ("STRING");
105 win32_atom = GPOINTER_TO_UINT (atom);
107 if (win32_atom < 0xC000)
108 return g_strdup_printf ("#%p", atom);
109 else if (GlobalGetAtomName (win32_atom, name, sizeof (name)) == 0)
111 return g_strdup (name);
115 gdk_property_get (GdkWindow *window,
121 GdkAtom *actual_property_type,
122 gint *actual_format_type,
126 g_return_val_if_fail (window != NULL, FALSE);
127 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
129 if (GDK_WINDOW_DESTROYED (window))
132 g_warning ("gdk_property_get: Not implemented");
138 find_common_locale (const guchar *data,
149 #define ENTRY(lang, sublang) \
150 { MAKELCID (MAKELANGID (LANG_##lang, SUBLANG_##sublang), SORT_DEFAULT), 0 }
151 ENTRY (ENGLISH, DEFAULT),
152 ENTRY (POLISH, DEFAULT),
153 ENTRY (CZECH, DEFAULT),
154 ENTRY (LITHUANIAN, DEFAULT),
155 ENTRY (RUSSIAN, DEFAULT),
156 ENTRY (GREEK, DEFAULT),
157 ENTRY (TURKISH, DEFAULT),
158 ENTRY (HEBREW, DEFAULT),
159 ENTRY (ARABIC, DEFAULT),
160 ENTRY (THAI, DEFAULT),
161 ENTRY (JAPANESE, DEFAULT),
162 ENTRY (CHINESE, CHINESE_SIMPLIFIED),
163 ENTRY (CHINESE, CHINESE_TRADITIONAL),
164 ENTRY (KOREAN, DEFAULT),
168 static gboolean been_here = FALSE;
172 /* For each installed locale: Get the locale's default code page,
173 * and store the list of locales and code pages.
178 for (i = 0; i < G_N_ELEMENTS (locales); i++)
179 if (IsValidLocale (locales[i].lcid, LCID_INSTALLED))
182 if (GetLocaleInfo (locales[i].lcid, LOCALE_IDEFAULTANSICODEPAGE,
186 locales[i].cp = atoi (buf);
187 GDK_NOTE (DND, (GetLocaleInfo (locales[i].lcid,
189 name, sizeof (name)),
190 g_print ("locale %#lx: %s: CP%d\n",
191 (gulong) locales[i].lcid, name,
197 /* Allocate bufp big enough to store data in any code page. Two
198 * bytes for each Unicode char should be enough, Windows code pages
199 * are either single- or double-byte.
201 *bufp = g_malloc ((nchars+1)*2);
203 /* Convert to Windows wide chars into temp buf */
204 wcs = g_utf8_to_utf16 (data, nelements, NULL, NULL, NULL);
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;
256 enum { SYSTEM_CODEPAGE, 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: %p %#x (%s) %#x (%s) %s %d*%d bytes %.10s\n",
269 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 && GetACP () == 1252) ||
282 type == _utf8_string)
284 && mode == GDK_PROP_MODE_REPLACE)
286 if (!OpenClipboard (GDK_WINDOW_HWND (window)))
288 WIN32_API_FAILED ("OpenClipboard");
292 if (type == _utf8_string)
294 /* Check if only ASCII */
295 for (i = 0; i < nelements; i++)
299 else /* if (type == GDK_TARGET_STRING) */
301 /* Check that no 0200..0240 chars present, as they
302 * differ between ISO-8859-1 and CP1252.
304 for (i = 0; i < nelements; i++)
305 if (data[i] >= 0200 && data[i] < 0240)
308 nchars = g_utf8_strlen (data, nelements);
312 /* If UTF-8 and only ASCII, or if STRING (ISO-8859-1) and
313 * system codepage is CP1252, use CF_TEXT and the data as
316 method = SYSTEM_CODEPAGE;
318 for (i = 0; i < nelements; i++)
322 GDK_NOTE (DND, g_print ("...as text: %.40s\n", data));
324 else if (IS_WIN_NT ())
326 /* On NT, use CF_UNICODETEXT if any non-system codepage char
329 method = UNICODE_TEXT;
331 wcptr = g_utf8_to_utf16 (data, nelements, NULL, &wclen, NULL);
333 wclen++; /* Terminating 0 */
335 GDK_NOTE (DND, g_print ("...as Unicode\n"));
337 else if (find_common_locale (data, nelements, nchars, &lcid, &buf, &size))
339 /* On Win9x, if all chars are in the default code page of
340 * some installed locale, use CF_TEXT and CF_LOCALE.
342 method = SINGLE_LOCALE;
343 GDK_NOTE (DND, g_print ("...as text in locale %#lx %d bytes\n",
344 (gulong) lcid, size));
348 /* On Win9x, otherwise use RTF */
350 const guchar *p = data;
353 rtf = g_string_new ("{\\rtf1\\uc0 ");
355 while (p < data + nelements)
361 rtf = g_string_append_c (rtf, '\\');
362 rtf = g_string_append_c (rtf, *p);
365 else if (*p < 0200 && *p >= ' ')
367 rtf = g_string_append_c (rtf, *p);
375 rtf = g_string_append (rtf, "\\uNNNNN ");
376 rtf->len -= 6; /* five digits and a space */
377 q = rtf->str + rtf->len;
378 n = g_sprintf (q, "%d ", g_utf8_get_char (p));
382 p = g_utf8_next_char (p);
385 rtf = g_string_append (rtf, "}");
387 GDK_NOTE (DND, g_print ("...as RTF: %.40s\n", rtf->str));
390 if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
392 WIN32_API_FAILED ("GlobalAlloc");
393 if (!CloseClipboard ())
394 WIN32_API_FAILED ("CloseClipboard");
398 g_string_free (rtf, TRUE);
402 ucptr = GlobalLock (hdata);
406 case SYSTEM_CODEPAGE:
408 for (i = 0; i < nelements; i++)
419 memmove (ucptr, wcptr, size);
425 memmove (ucptr, buf, size);
428 /* Set the CF_LOCALE clipboard data, too */
429 if (!(hlcid = GlobalAlloc (GMEM_MOVEABLE, sizeof (LCID))))
430 WIN32_API_FAILED ("GlobalAlloc"), ok = FALSE;
433 lcidptr = GlobalLock (hlcid);
435 GlobalUnlock (hlcid);
436 if (!SetClipboardData (CF_LOCALE, hlcid))
437 WIN32_API_FAILED ("SetClipboardData (CF_LOCALE)"), ok = FALSE;
443 memmove (ucptr, rtf->str, size);
444 g_string_free (rtf, TRUE);
446 /* Set the UTF8_STRING clipboard data, too, for other
447 * GTK+ apps to use (won't bother reading RTF).
449 if (!(hutf8 = GlobalAlloc (GMEM_MOVEABLE, nelements)))
450 WIN32_API_FAILED ("GlobalAlloc");
453 guchar *utf8ptr = GlobalLock (hutf8);
454 memmove (utf8ptr, data, nelements);
455 GlobalUnlock (hutf8);
456 if (!SetClipboardData (_cf_utf8_string, hutf8))
457 WIN32_API_FAILED ("SetClipboardData (UTF8_STRING)");
462 g_assert_not_reached ();
465 GlobalUnlock (hdata);
466 if (ok && !SetClipboardData (cf, hdata))
467 WIN32_API_FAILED ("SetClipboardData"), ok = FALSE;
469 if (!CloseClipboard ())
470 WIN32_API_FAILED ("CloseClipboard");
473 g_warning ("gdk_property_change: General case not implemented");
477 gdk_property_delete (GdkWindow *window,
482 g_return_if_fail (window != NULL);
483 g_return_if_fail (GDK_IS_WINDOW (window));
486 (prop_name = gdk_atom_name (property),
487 g_print ("gdk_property_delete: %p %#x (%s)\n",
488 GDK_WINDOW_HWND (window),
489 (guint) property, prop_name),
490 g_free (prop_name)));
492 if (property == _gdk_selection_property)
493 _gdk_selection_property_delete (window);
494 else if (property == _wm_transient_for)
495 gdk_window_set_transient_for (window, _gdk_parent_root);
498 prop_name = gdk_atom_name (property);
499 g_warning ("gdk_property_delete: General case (%s) not implemented",
506 for reference copied from gdk/x11/gdkevents-x11.c
508 { "Net/DoubleClickTime", "gtk-double-click-time" },
509 { "Net/DoubleClickDistance", "gtk-double-click-distance" },
510 { "Net/DndDragThreshold", "gtk-dnd-drag-threshold" },
511 { "Gtk/CanChangeAccels", "gtk-can-change-accels" },
512 { "Gtk/ColorPalette", "gtk-color-palette" },
513 { "Gtk/FontName", "gtk-font-name" },
514 { "Gtk/IconSizes", "gtk-icon-sizes" },
515 { "Gtk/KeyThemeName", "gtk-key-theme-name" },
516 { "Gtk/ToolbarStyle", "gtk-toolbar-style" },
517 { "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
518 { "Gtk/IMPreeditStyle", "gtk-im-preedit-style" },
519 { "Gtk/IMStatusStyle", "gtk-im-status-style" },
520 { "Net/CursorBlink", "gtk-cursor-blink" },
521 { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
522 { "Net/ThemeName", "gtk-theme-name" },
523 { "Net/IconThemeName", "gtk-icon-theme-name" },
524 { "Gtk/ButtonImages", "gtk-button-images" },
525 { "Gtk/MenuImages", "gtk-menu-images" },
526 { "Xft/Antialias", "gtk-xft-antialias" },
527 { "Xft/Hinting", "gtk-xft-hinting" },
528 { "Xft/HintStyle", "gtk-xft-hintstyle" },
529 { "Xft/RGBA", "gtk-xft-rgba" },
530 { "Xft/DPI", "gtk-xft-dpi" },
532 // more spread in gtk sources
533 gtk-entry-select-on-focus
535 gtk-cursor-blink-time
540 gdk_screen_get_setting (GdkScreen *screen,
544 g_return_val_if_fail (screen == gdk_screen_get_default (), FALSE);
547 * XXX : if these values get changed through the Windoze UI the
548 * respective gdk_events are not generated yet.
550 if (strcmp ("gtk-double-click-time", name) == 0)
552 gint i = GetDoubleClickTime ();
553 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
554 g_value_set_int (value, i);
557 else if (strcmp ("gtk-double-click-distance", name) == 0)
559 gint i = MAX(GetSystemMetrics (SM_CXDOUBLECLK), GetSystemMetrics (SM_CYDOUBLECLK));
560 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
561 g_value_set_int (value, i);
564 else if (strcmp ("gtk-dnd-drag-threshold", name) == 0)
566 gint i = MAX(GetSystemMetrics (SM_CXDRAG), GetSystemMetrics (SM_CYDRAG));
567 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
568 g_value_set_int (value, i);
571 else if (strcmp ("gtk-split-cursor", name) == 0)
573 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : FALSE\n", name));
574 g_value_set_boolean (value, FALSE);
579 * With 'MS Sans Serif' as windows menu font (default on win98se) you'll get a
581 * WARNING **: Couldn't load font "MS Sans Serif 8" falling back to "Sans 8"
582 * at least with testfilechooser (regardless of the bitmap check below)
583 * so just disabling this code seems to be the best we can do --hb
585 else if (strcmp ("gtk-font-name", name) == 0)
587 NONCLIENTMETRICS ncm;
588 ncm.cbSize = sizeof(NONCLIENTMETRICS);
589 if (SystemParametersInfo (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, FALSE))
591 /* Pango finally uses GetDeviceCaps to scale, we use simple approximation here */
592 int nHeight = (0 > ncm.lfMenuFont.lfHeight ? -3*ncm.lfMenuFont.lfHeight/4 : 10);
593 if (OUT_STRING_PRECIS == ncm.lfMenuFont.lfOutPrecision)
594 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) : ignoring bitmap font '%s'\n",
595 name, ncm.lfMenuFont.lfFaceName));
596 else if (ncm.lfMenuFont.lfFaceName && strlen(ncm.lfMenuFont.lfFaceName) > 0 &&
597 /* avoid issues like those described in bug #135098 */
598 g_utf8_validate (ncm.lfMenuFont.lfFaceName, -1, NULL))
600 char* s = g_strdup_printf ("%s %d", ncm.lfMenuFont.lfFaceName, nHeight);
601 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) : %s\n", name, s));
602 g_value_set_string (value, s);
611 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) not handled\n", name));