]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkproperty-win32.c
Check that GDK_IS_SCREEN(screen) (like the X11 backend does), not screen
[~andy/gtk] / gdk / win32 / gdkproperty-win32.c
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
4  *
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.
9  *
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.
14  *
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.
19  */
20
21 /*
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/. 
26  */
27
28 #include <config.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <glib/gprintf.h>
32
33 #include "gdkscreen.h"
34 #include "gdkproperty.h"
35 #include "gdkselection.h"
36 #include "gdkprivate-win32.h"
37
38 GdkAtom
39 gdk_atom_intern (const gchar *atom_name,
40                  gint         only_if_exists)
41 {
42   ATOM win32_atom;
43   GdkAtom retval;
44   static GHashTable *atom_hash = NULL;
45   
46   if (!atom_hash)
47     atom_hash = g_hash_table_new (g_str_hash, g_str_equal);
48
49   retval = g_hash_table_lookup (atom_hash, atom_name);
50   if (!retval)
51     {
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;
74       else
75         {
76           win32_atom = GlobalAddAtom (atom_name);
77           retval = GUINT_TO_POINTER ((guint) win32_atom);
78         }
79       g_hash_table_insert (atom_hash, 
80                            g_strdup (atom_name), 
81                            retval);
82     }
83
84   return retval;
85 }
86
87 gchar *
88 gdk_atom_name (GdkAtom atom)
89 {
90   ATOM win32_atom;
91   gchar name[256];
92
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");
104   
105   win32_atom = GPOINTER_TO_UINT (atom);
106   
107   if (win32_atom < 0xC000)
108     return g_strdup_printf ("#%p", atom);
109   else if (GlobalGetAtomName (win32_atom, name, sizeof (name)) == 0)
110     return NULL;
111   return g_strdup (name);
112 }
113
114 gint
115 gdk_property_get (GdkWindow   *window,
116                   GdkAtom      property,
117                   GdkAtom      type,
118                   gulong       offset,
119                   gulong       length,
120                   gint         pdelete,
121                   GdkAtom     *actual_property_type,
122                   gint        *actual_format_type,
123                   gint        *actual_length,
124                   guchar     **data)
125 {
126   g_return_val_if_fail (window != NULL, FALSE);
127   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
128
129   if (GDK_WINDOW_DESTROYED (window))
130     return FALSE;
131
132   g_warning ("gdk_property_get: Not implemented");
133
134   return FALSE;
135 }
136
137 static gboolean
138 find_common_locale (const guchar  *data,
139                     gint           nelements,
140                     gint           nchars,
141                     LCID          *lcidp,
142                     guchar       **bufp,
143                     gint          *sizep)
144 {
145   static struct {
146     LCID lcid;
147     UINT cp;
148   } locales[] = {
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),
165 #undef ENTRY
166   };
167
168   static gboolean been_here = FALSE;
169   gint i;
170   wchar_t *wcs;
171
172   /* For each installed locale: Get the locale's default code page,
173    * and store the list of locales and code pages.
174    */
175   if (!been_here)
176     {
177       been_here = TRUE;
178       for (i = 0; i < G_N_ELEMENTS (locales); i++)
179         if (IsValidLocale (locales[i].lcid, LCID_INSTALLED))
180           {
181             gchar buf[10];
182             if (GetLocaleInfo (locales[i].lcid, LOCALE_IDEFAULTANSICODEPAGE,
183                                buf, sizeof (buf)))
184               {
185                 gchar name[100];
186                 locales[i].cp = atoi (buf);
187                 GDK_NOTE (DND, (GetLocaleInfo (locales[i].lcid,
188                                                LOCALE_SENGLANGUAGE,
189                                                name, sizeof (name)),
190                                 g_print ("locale %#lx: %s: CP%d\n",
191                                          (gulong) locales[i].lcid, name,
192                                          locales[i].cp)));
193               }
194           }
195     }
196   
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.
200    */
201   *bufp = g_malloc ((nchars+1)*2);
202
203   /* Convert to Windows wide chars into temp buf */
204   wcs = g_utf8_to_utf16 (data, nelements, NULL, NULL, NULL);
205
206   /* For each code page that is the default for an installed locale: */
207   for (i = 0; i < G_N_ELEMENTS (locales); i++)
208     {
209       BOOL used_default;
210       int nbytes;
211
212       if (locales[i].cp == 0)
213         continue;
214
215       /* Convert to that code page into bufp */
216       
217       nbytes = WideCharToMultiByte (locales[i].cp, 0, wcs, -1,
218                                     *bufp, (nchars+1)*2,
219                                     NULL, &used_default);
220
221       if (!used_default)
222         {
223           /* This locale is good for the string */
224           g_free (wcs);
225           *lcidp = locales[i].lcid;
226           *sizep = nbytes;
227           return TRUE;
228         }
229     }
230
231   g_free (*bufp);
232   g_free (wcs);
233
234   return FALSE;
235 }
236
237 void
238 gdk_property_change (GdkWindow    *window,
239                      GdkAtom       property,
240                      GdkAtom       type,
241                      gint          format,
242                      GdkPropMode   mode,
243                      const guchar *data,
244                      gint          nelements)
245 {
246   HGLOBAL hdata, hlcid, hutf8;
247   UINT cf = 0;
248   LCID lcid;
249   LCID *lcidptr;
250   GString *rtf = NULL;
251   gint i, size, nchars;
252   gchar *prop_name, *type_name;
253   guchar *ucptr, *buf = NULL;
254   wchar_t *wcptr;
255   glong wclen;
256   enum { SYSTEM_CODEPAGE, UNICODE_TEXT, SINGLE_LOCALE, RICH_TEXT } method;
257   gboolean ok = TRUE;
258
259   g_return_if_fail (window != NULL);
260   g_return_if_fail (GDK_IS_WINDOW (window));
261
262   if (GDK_WINDOW_DESTROYED (window))
263     return;
264
265   GDK_NOTE (DND,
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: %s\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" :
275                          "???"))),
276                       format, nelements,
277                       _gdk_win32_data_to_string (data, MIN (10, format*nelements/8))),
278              g_free (prop_name),
279              g_free (type_name)));
280
281   if (property == _gdk_selection_property
282       && format == 8
283       && mode == GDK_PROP_MODE_REPLACE)
284     {
285       if ((type == GDK_TARGET_STRING && GetACP () == 1252) ||
286           type == _utf8_string)
287         {
288           if (!OpenClipboard (GDK_WINDOW_HWND (window)))
289             {
290               WIN32_API_FAILED ("OpenClipboard");
291               return;
292             }
293
294           if (type == _utf8_string)
295             {
296               /* Check if only ASCII */
297               for (i = 0; i < nelements; i++)
298                 if (data[i] >= 0200)
299                   break;
300             }
301           else /* if (type == GDK_TARGET_STRING) */
302             {
303               /* Check that no 0200..0240 chars present, as they
304                * differ between ISO-8859-1 and CP1252.
305                */
306               for (i = 0; i < nelements; i++)
307                 if (data[i] >= 0200 && data[i] < 0240)
308                   break;
309             }
310           nchars = g_utf8_strlen (data, nelements);
311
312           if (i == nelements)
313             {
314               /* If UTF-8 and only ASCII, or if STRING (ISO-8859-1)
315                * and system codepage is CP1252, use CF_TEXT and the
316                * data as such.
317                */
318               method = SYSTEM_CODEPAGE;
319               size = nelements;
320               for (i = 0; i < nelements; i++)
321                 if (data[i] == '\n')
322                   size++;
323               size++;
324               GDK_NOTE (DND, g_print ("... as text: %.40s\n", data));
325             }
326           else if (G_WIN32_IS_NT_BASED ())
327             {
328               /* On NT, use CF_UNICODETEXT if any non-system codepage
329                * char present.
330                */
331               method = UNICODE_TEXT;
332
333               wcptr = g_utf8_to_utf16 (data, nelements, NULL, &wclen, NULL);
334
335               wclen++;          /* Terminating 0 */
336               size = wclen * 2;
337               GDK_NOTE (DND, g_print ("... as Unicode\n"));
338             }
339           else if (find_common_locale (data, nelements, nchars, &lcid, &buf, &size))
340             {
341               /* On Win9x, if all chars are in the default code page
342                * of some installed locale, use CF_TEXT and CF_LOCALE.
343                */
344               method = SINGLE_LOCALE;
345               GDK_NOTE (DND, g_print ("... as text in locale %#lx %d bytes\n",
346                                       (gulong) lcid, size));
347             }
348           else
349             {
350               /* On Win9x, otherwise use RTF */
351
352               const guchar *p = data;
353
354               method = RICH_TEXT;
355               rtf = g_string_new ("{\\rtf1\\uc0 ");
356
357               while (p < data + nelements)
358                 {
359                   if (*p == '{' ||
360                       *p == '\\' ||
361                       *p == '}')
362                     {
363                       rtf = g_string_append_c (rtf, '\\');
364                       rtf = g_string_append_c (rtf, *p);
365                       p++;
366                     }
367                   else if (*p < 0200 && *p >= ' ')
368                     {
369                       rtf = g_string_append_c (rtf, *p);
370                       p++;
371                     }
372                   else
373                     {
374                       guchar *q;
375                       gint n;
376                       
377                       rtf = g_string_append (rtf, "\\uNNNNN ");
378                       rtf->len -= 6; /* five digits and a space */
379                       q = rtf->str + rtf->len;
380                       n = g_sprintf (q, "%d ", g_utf8_get_char (p));
381                       g_assert (n <= 6);
382                       rtf->len += n;
383                       
384                       p = g_utf8_next_char (p);
385                     }
386                 }
387               rtf = g_string_append (rtf, "}");
388               size = rtf->len + 1;
389               GDK_NOTE (DND, g_print ("... as RTF: %.40s\n", rtf->str));
390             }
391           
392           if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
393             {
394               WIN32_API_FAILED ("GlobalAlloc");
395               if (!CloseClipboard ())
396                 WIN32_API_FAILED ("CloseClipboard");
397               if (buf != NULL)
398                 g_free (buf);
399               if (rtf != NULL)
400                 g_string_free (rtf, TRUE);
401               return;
402             }
403
404           ucptr = GlobalLock (hdata);
405
406           switch (method)
407             {
408             case SYSTEM_CODEPAGE:
409               cf = CF_TEXT;
410               for (i = 0; i < nelements; i++)
411                 {
412                   if (data[i] == '\n')
413                     *ucptr++ = '\r';
414                   *ucptr++ = data[i];
415                 }
416               *ucptr++ = '\0';
417               break;
418
419             case UNICODE_TEXT:
420               cf = CF_UNICODETEXT;
421               memmove (ucptr, wcptr, size);
422               g_free (wcptr);
423               break;
424
425             case SINGLE_LOCALE:
426               cf = CF_TEXT;
427               memmove (ucptr, buf, size);
428               g_free (buf);
429
430               /* Set the CF_LOCALE clipboard data, too */
431               if (!(hlcid = GlobalAlloc (GMEM_MOVEABLE, sizeof (LCID))))
432                 WIN32_API_FAILED ("GlobalAlloc"), ok = FALSE;
433               if (ok)
434                 {
435                   lcidptr = GlobalLock (hlcid);
436                   *lcidptr = lcid;
437                   GlobalUnlock (hlcid);
438                   if (!SetClipboardData (CF_LOCALE, hlcid))
439                     WIN32_API_FAILED ("SetClipboardData (CF_LOCALE)"), ok = FALSE;
440                 }
441               break;
442
443             case RICH_TEXT:
444               cf = _cf_rtf;
445               memmove (ucptr, rtf->str, size);
446               g_string_free (rtf, TRUE);
447
448               /* Set the UTF8_STRING clipboard data, too, for other
449                * GTK+ apps to use (won't bother reading RTF).
450                */
451               if (!(hutf8 = GlobalAlloc (GMEM_MOVEABLE, nelements)))
452                 WIN32_API_FAILED ("GlobalAlloc");
453               else
454                 {
455                   guchar *utf8ptr = GlobalLock (hutf8);
456                   memmove (utf8ptr, data, nelements);
457                   GlobalUnlock (hutf8);
458                   if (!SetClipboardData (_cf_utf8_string, hutf8))
459                     WIN32_API_FAILED ("SetClipboardData (UTF8_STRING)");
460                 }
461               break;
462
463             default:
464               g_assert_not_reached ();
465             }
466
467           GlobalUnlock (hdata);
468           if (ok && !SetClipboardData (cf, hdata))
469             WIN32_API_FAILED ("SetClipboardData"), ok = FALSE;
470       
471           if (!CloseClipboard ())
472             WIN32_API_FAILED ("CloseClipboard");
473         }
474       else
475         {
476           /* Delayed Rendering. We can't assign hdata to the clipboard
477            * here as type may be "image/png", "image/jpg", etc.  In
478            * this case there's a further conversion afterwards.
479            */
480           _delayed_rendering_data = NULL;
481           if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, nelements > 0 ? nelements : 1)))
482             {
483               WIN32_API_FAILED ("GlobalAlloc");
484               return;
485             }
486           ucptr = GlobalLock (hdata);
487           memcpy (ucptr, data, nelements);
488           GlobalUnlock (hdata);
489           _delayed_rendering_data = hdata;
490         }
491     }
492   else
493     g_warning ("gdk_property_change: General case not implemented");
494 }
495
496 void
497 gdk_property_delete (GdkWindow *window,
498                      GdkAtom    property)
499 {
500   gchar *prop_name;
501
502   g_return_if_fail (window != NULL);
503   g_return_if_fail (GDK_IS_WINDOW (window));
504
505   GDK_NOTE (DND,
506             (prop_name = gdk_atom_name (property),
507              g_print ("gdk_property_delete: %p %#x (%s)\n",
508                       GDK_WINDOW_HWND (window),
509                       (guint) property, prop_name),
510              g_free (prop_name)));
511
512   if (property == _gdk_selection_property)
513     _gdk_selection_property_delete (window);
514   else if (property == _wm_transient_for)
515     gdk_window_set_transient_for (window, _gdk_root);
516   else
517     {
518       prop_name = gdk_atom_name (property);
519       g_warning ("gdk_property_delete: General case (%s) not implemented",
520                  prop_name);
521       g_free (prop_name);
522     }
523 }
524
525 /*
526   for reference copied from gdk/x11/gdkevents-x11.c
527
528   { "Net/DoubleClickTime", "gtk-double-click-time" },
529   { "Net/DoubleClickDistance", "gtk-double-click-distance" },
530   { "Net/DndDragThreshold", "gtk-dnd-drag-threshold" },
531   { "Gtk/CanChangeAccels", "gtk-can-change-accels" },
532   { "Gtk/ColorPalette", "gtk-color-palette" },
533   { "Gtk/FontName", "gtk-font-name" },
534   { "Gtk/IconSizes", "gtk-icon-sizes" },
535   { "Gtk/KeyThemeName", "gtk-key-theme-name" },
536   { "Gtk/ToolbarStyle", "gtk-toolbar-style" },
537   { "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
538   { "Gtk/IMPreeditStyle", "gtk-im-preedit-style" },
539   { "Gtk/IMStatusStyle", "gtk-im-status-style" },
540   { "Net/CursorBlink", "gtk-cursor-blink" },
541   { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
542   { "Net/ThemeName", "gtk-theme-name" },
543   { "Net/IconThemeName", "gtk-icon-theme-name" },
544   { "Gtk/ButtonImages", "gtk-button-images" },
545   { "Gtk/MenuImages", "gtk-menu-images" },
546   { "Xft/Antialias", "gtk-xft-antialias" },
547   { "Xft/Hinting", "gtk-xft-hinting" },
548   { "Xft/HintStyle", "gtk-xft-hintstyle" },
549   { "Xft/RGBA", "gtk-xft-rgba" },
550   { "Xft/DPI", "gtk-xft-dpi" },
551
552   // more spread in gtk sources
553   gtk-entry-select-on-focus
554   gtk-cursor-blink
555   gtk-cursor-blink-time
556   gtk-split-cursor
557
558 */
559 gboolean
560 gdk_screen_get_setting (GdkScreen   *screen,
561                         const gchar *name,
562                         GValue      *value)
563 {
564   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
565
566   /*
567    * XXX : if these values get changed through the Windoze UI the
568    *       respective gdk_events are not generated yet.
569    */
570   if (strcmp ("gtk-theme-name", name) == 0) 
571     {
572       g_value_set_string (value, "ms-windows");
573     }
574   else if (strcmp ("gtk-double-click-time", name) == 0)
575     {
576       gint i = GetDoubleClickTime ();
577       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
578       g_value_set_int (value, i);
579       return TRUE;
580     }
581   else if (strcmp ("gtk-double-click-distance", name) == 0)
582     {
583       gint i = MAX(GetSystemMetrics (SM_CXDOUBLECLK), GetSystemMetrics (SM_CYDOUBLECLK));
584       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
585       g_value_set_int (value, i);
586       return TRUE;
587     }
588   else if (strcmp ("gtk-dnd-drag-threshold", name) == 0)
589     {
590       gint i = MAX(GetSystemMetrics (SM_CXDRAG), GetSystemMetrics (SM_CYDRAG));
591       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
592       g_value_set_int (value, i);
593       return TRUE;
594     }
595   else if (strcmp ("gtk-split-cursor", name) == 0)
596     {
597       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : FALSE\n", name));
598       g_value_set_boolean (value, FALSE);
599       return TRUE;
600     }
601 #if 0
602   /*
603    * With 'MS Sans Serif' as windows menu font (default on win98se) you'll get a 
604    * bunch of :
605    *   WARNING **: Couldn't load font "MS Sans Serif 8" falling back to "Sans 8"
606    * at least with testfilechooser (regardless of the bitmap check below)
607    * so just disabling this code seems to be the best we can do --hb
608    */
609   else if (strcmp ("gtk-font-name", name) == 0)
610     {
611       NONCLIENTMETRICS ncm;
612       ncm.cbSize = sizeof(NONCLIENTMETRICS);
613       if (SystemParametersInfo (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, FALSE))
614         {
615           /* Pango finally uses GetDeviceCaps to scale, we use simple
616            * approximation here.
617            */
618           int nHeight = (0 > ncm.lfMenuFont.lfHeight ? -3*ncm.lfMenuFont.lfHeight/4 : 10);
619           if (OUT_STRING_PRECIS == ncm.lfMenuFont.lfOutPrecision)
620             GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) : ignoring bitmap font '%s'\n", 
621                                    name, ncm.lfMenuFont.lfFaceName));
622           else if (ncm.lfMenuFont.lfFaceName && strlen(ncm.lfMenuFont.lfFaceName) > 0 &&
623                    /* Avoid issues like those described in bug #135098 */
624                    g_utf8_validate (ncm.lfMenuFont.lfFaceName, -1, NULL))
625             {
626               char* s = g_strdup_printf ("%s %d", ncm.lfMenuFont.lfFaceName, nHeight);
627               GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) : %s\n", name, s));
628               g_value_set_string (value, s);
629
630               g_free(s);
631               return TRUE;
632             }
633         }
634     }
635 #endif
636
637   GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) not handled\n", name));
638   return FALSE;
639 }