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);
202 wcs = g_new (wchar_t, nchars+1);
204 /* Convert to Windows wide chars into temp buf */
205 _gdk_utf8_to_ucs2 (wcs, data, nelements, nchars);
208 /* For each code page that is the default for an installed locale: */
209 for (i = 0; i < G_N_ELEMENTS (locales); i++)
214 if (locales[i].cp == 0)
217 /* Convert to that code page into bufp */
219 nbytes = WideCharToMultiByte (locales[i].cp, 0, wcs, -1,
221 NULL, &used_default);
225 /* This locale is good for the string */
227 *lcidp = locales[i].lcid;
240 gdk_property_change (GdkWindow *window,
248 HGLOBAL hdata, hlcid, hutf8;
253 gint i, size, nchars;
254 gchar *prop_name, *type_name;
255 guchar *ucptr, *buf = NULL;
257 enum { PLAIN_ASCII, UNICODE_TEXT, SINGLE_LOCALE, RICH_TEXT } method;
260 g_return_if_fail (window != NULL);
261 g_return_if_fail (GDK_IS_WINDOW (window));
263 if (GDK_WINDOW_DESTROYED (window))
267 (prop_name = gdk_atom_name (property),
268 type_name = gdk_atom_name (type),
269 g_print ("gdk_property_change: %p %#x (%s) %#x (%s) %s %d*%d bytes %.10s\n",
270 GDK_WINDOW_HWND (window),
271 (guint) property, prop_name,
272 (guint) type, type_name,
273 (mode == GDK_PROP_MODE_REPLACE ? "REPLACE" :
274 (mode == GDK_PROP_MODE_PREPEND ? "PREPEND" :
275 (mode == GDK_PROP_MODE_APPEND ? "APPEND" :
277 format, nelements, data),
279 g_free (type_name)));
281 if (property == _gdk_selection_property
282 && type == GDK_TARGET_STRING
284 && mode == GDK_PROP_MODE_REPLACE)
286 if (!OpenClipboard (GDK_WINDOW_HWND (window)))
288 WIN32_API_FAILED ("OpenClipboard");
292 /* Check if only ASCII */
293 for (i = 0; i < nelements; i++)
300 nchars = g_utf8_strlen (data, nelements);
302 GDK_NOTE (DND, g_print ("...nchars:%d\n", nchars));
306 /* If only ASCII, use CF_TEXT and the data as such. */
307 method = PLAIN_ASCII;
309 for (i = 0; i < nelements; i++)
313 GDK_NOTE (DND, g_print ("...as text: %.40s\n", data));
315 else if (IS_WIN_NT ())
317 /* On NT, use CF_UNICODETEXT if any non-ASCII char present */
318 method = UNICODE_TEXT;
319 size = (nchars + 1) * 2;
320 GDK_NOTE (DND, g_print ("...as Unicode\n"));
322 else if (find_common_locale (data, nelements, nchars, &lcid, &buf, &size))
324 /* On Win9x, if all chars are in the default code page of
325 * some installed locale, use CF_TEXT and CF_LOCALE.
327 method = SINGLE_LOCALE;
328 GDK_NOTE (DND, g_print ("...as text in locale %#lx %d bytes\n",
329 (gulong) lcid, size));
333 /* On Win9x, otherwise use RTF */
335 const guchar *p = data;
338 rtf = g_string_new ("{\\rtf1\\uc0 ");
340 while (p < data + nelements)
346 rtf = g_string_append_c (rtf, '\\');
347 rtf = g_string_append_c (rtf, *p);
352 rtf = g_string_append_c (rtf, *p);
360 rtf = g_string_append (rtf, "\\uNNNNN ");
361 rtf->len -= 6; /* five digits and a space */
362 q = rtf->str + rtf->len;
363 n = g_sprintf (q, "%d ", g_utf8_get_char (p));
367 p = g_utf8_next_char (p);
370 rtf = g_string_append (rtf, "}");
372 GDK_NOTE (DND, g_print ("...as RTF: %.40s\n", rtf->str));
375 if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
377 WIN32_API_FAILED ("GlobalAlloc");
378 if (!CloseClipboard ())
379 WIN32_API_FAILED ("CloseClipboard");
383 g_string_free (rtf, TRUE);
387 ucptr = GlobalLock (hdata);
393 for (i = 0; i < nelements; i++)
404 wcptr = (wchar_t *) ucptr;
405 if (_gdk_utf8_to_ucs2 (wcptr, data, nelements, nchars) == -1)
406 g_warning ("_gdk_utf8_to_ucs2() failed");
412 memmove (ucptr, buf, size);
415 /* Set the CF_LOCALE clipboard data, too */
416 if (!(hlcid = GlobalAlloc (GMEM_MOVEABLE, sizeof (LCID))))
417 WIN32_API_FAILED ("GlobalAlloc"), ok = FALSE;
420 lcidptr = GlobalLock (hlcid);
422 GlobalUnlock (hlcid);
423 if (!SetClipboardData (CF_LOCALE, hlcid))
424 WIN32_API_FAILED ("SetClipboardData (CF_LOCALE)"), ok = FALSE;
430 memmove (ucptr, rtf->str, size);
431 g_string_free (rtf, TRUE);
433 /* Set the UTF8_STRING clipboard data, too, for other
434 * GTK+ apps to use (won't bother reading RTF).
436 if (!(hutf8 = GlobalAlloc (GMEM_MOVEABLE, nelements)))
437 WIN32_API_FAILED ("GlobalAlloc");
440 guchar *utf8ptr = GlobalLock (hutf8);
441 memmove (utf8ptr, data, nelements);
442 GlobalUnlock (hutf8);
443 if (!SetClipboardData (_cf_utf8_string, hutf8))
444 WIN32_API_FAILED ("SetClipboardData (UTF8_STRING)");
449 g_assert_not_reached ();
452 GlobalUnlock (hdata);
453 if (ok && !SetClipboardData (cf, hdata))
454 WIN32_API_FAILED ("SetClipboardData"), ok = FALSE;
456 if (!CloseClipboard ())
457 WIN32_API_FAILED ("CloseClipboard");
460 g_warning ("gdk_property_change: General case not implemented");
464 gdk_property_delete (GdkWindow *window,
469 g_return_if_fail (window != NULL);
470 g_return_if_fail (GDK_IS_WINDOW (window));
473 (prop_name = gdk_atom_name (property),
474 g_print ("gdk_property_delete: %p %#x (%s)\n",
475 GDK_WINDOW_HWND (window),
476 (guint) property, prop_name),
477 g_free (prop_name)));
479 if (property == _gdk_selection_property)
480 _gdk_selection_property_delete (window);
481 else if (property == _wm_transient_for)
482 gdk_window_set_transient_for (window, _gdk_parent_root);
485 prop_name = gdk_atom_name (property);
486 g_warning ("gdk_property_delete: General case (%s) not implemented",
493 for reference copied from gdk/x11/gdkevents-x11.c
495 { "Net/DoubleClickTime", "gtk-double-click-time" },
496 { "Net/DoubleClickDistance", "gtk-double-click-distance" },
497 { "Net/DndDragThreshold", "gtk-dnd-drag-threshold" },
498 { "Gtk/CanChangeAccels", "gtk-can-change-accels" },
499 { "Gtk/ColorPalette", "gtk-color-palette" },
500 { "Gtk/FontName", "gtk-font-name" },
501 { "Gtk/IconSizes", "gtk-icon-sizes" },
502 { "Gtk/KeyThemeName", "gtk-key-theme-name" },
503 { "Gtk/ToolbarStyle", "gtk-toolbar-style" },
504 { "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
505 { "Gtk/IMPreeditStyle", "gtk-im-preedit-style" },
506 { "Gtk/IMStatusStyle", "gtk-im-status-style" },
507 { "Net/CursorBlink", "gtk-cursor-blink" },
508 { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
509 { "Net/ThemeName", "gtk-theme-name" },
510 { "Net/IconThemeName", "gtk-icon-theme-name" },
511 { "Gtk/ButtonImages", "gtk-button-images" },
512 { "Gtk/MenuImages", "gtk-menu-images" },
513 { "Xft/Antialias", "gtk-xft-antialias" },
514 { "Xft/Hinting", "gtk-xft-hinting" },
515 { "Xft/HintStyle", "gtk-xft-hintstyle" },
516 { "Xft/RGBA", "gtk-xft-rgba" },
517 { "Xft/DPI", "gtk-xft-dpi" },
519 // more spread in gtk sources
520 gtk-entry-select-on-focus
522 gtk-cursor-blink-time
527 gdk_screen_get_setting (GdkScreen *screen,
531 g_return_val_if_fail (screen == gdk_screen_get_default (), FALSE);
534 * XXX : if these values get changed through the Windoze UI the
535 * respective gdk_events are not generated yet.
537 if (strcmp ("gtk-double-click-time", name) == 0)
539 gint i = GetDoubleClickTime ();
540 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
541 g_value_set_int (value, i);
544 else if (strcmp ("gtk-double-click-distance", name) == 0)
546 gint i = MAX(GetSystemMetrics (SM_CXDOUBLECLK), GetSystemMetrics (SM_CYDOUBLECLK));
547 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
548 g_value_set_int (value, i);
551 else if (strcmp ("gtk-dnd-drag-threshold", name) == 0)
553 gint i = MAX(GetSystemMetrics (SM_CXDRAG), GetSystemMetrics (SM_CYDRAG));
554 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
555 g_value_set_int (value, i);
558 else if (strcmp ("gtk-split-cursor", name) == 0)
560 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : FALSE\n", name));
561 g_value_set_boolean (value, FALSE);
566 * With 'MS Sans Serif' as windows menu font (default on win98se) you'll get a
568 * WARNING **: Couldn't load font "MS Sans Serif 8" falling back to "Sans 8"
569 * at least with testfilechooser (regardless of the bitmap check below)
570 * so just disabling this code seems to be the best we can do --hb
572 else if (strcmp ("gtk-font-name", name) == 0)
574 NONCLIENTMETRICS ncm;
575 ncm.cbSize = sizeof(NONCLIENTMETRICS);
576 if (SystemParametersInfo (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, FALSE))
578 /* Pango finally uses GetDeviceCaps to scale, we use simple approximation here */
579 int nHeight = (0 > ncm.lfMenuFont.lfHeight ? -3*ncm.lfMenuFont.lfHeight/4 : 10);
580 if (OUT_STRING_PRECIS == ncm.lfMenuFont.lfOutPrecision)
581 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) : ignoring bitmap font '%s'\n",
582 name, ncm.lfMenuFont.lfFaceName));
583 else if (ncm.lfMenuFont.lfFaceName && strlen(ncm.lfMenuFont.lfFaceName) > 0 &&
584 /* avoid issues like those described in bug #135098 */
585 g_utf8_validate (ncm.lfMenuFont.lfFaceName, -1, NULL))
587 char* s = g_strdup_printf ("%s %d", ncm.lfMenuFont.lfFaceName, nHeight);
588 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) : %s\n", name, s));
589 g_value_set_string (value, s);
598 GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) not handled\n", name));