]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkproperty-win32.c
Include "config.h" instead of <config.h> Command used: find -name
[~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 GdkAtom
88 gdk_atom_intern_static_string (const gchar *atom_name)
89 {
90   /* on X11 this is supposed to save memory. On win32 there seems to be
91    * no way to make a difference ?
92    */
93   return gdk_atom_intern (atom_name, FALSE);
94 }
95
96 gchar *
97 gdk_atom_name (GdkAtom atom)
98 {
99   ATOM win32_atom;
100   gchar name[256];
101
102   if (GDK_SELECTION_PRIMARY == atom) return g_strdup ("PRIMARY");
103   else if (GDK_SELECTION_SECONDARY == atom) return g_strdup ("SECONDARY");
104   else if (GDK_SELECTION_CLIPBOARD == atom) return g_strdup ("CLIPBOARD");
105   else if (GDK_SELECTION_TYPE_ATOM == atom) return g_strdup ("ATOM");
106   else if (GDK_SELECTION_TYPE_BITMAP == atom) return g_strdup ("BITMAP");
107   else if (GDK_SELECTION_TYPE_COLORMAP == atom) return g_strdup ("COLORMAP");
108   else if (GDK_SELECTION_TYPE_DRAWABLE == atom) return g_strdup ("DRAWABLE");
109   else if (GDK_SELECTION_TYPE_INTEGER == atom) return g_strdup ("INTEGER");
110   else if (GDK_SELECTION_TYPE_PIXMAP == atom) return g_strdup ("PIXMAP");
111   else if (GDK_SELECTION_TYPE_WINDOW == atom) return g_strdup ("WINDOW");
112   else if (GDK_SELECTION_TYPE_STRING == atom) return g_strdup ("STRING");
113   
114   win32_atom = GPOINTER_TO_UINT (atom);
115   
116   if (win32_atom < 0xC000)
117     return g_strdup_printf ("#%p", atom);
118   else if (GlobalGetAtomName (win32_atom, name, sizeof (name)) == 0)
119     return NULL;
120   return g_strdup (name);
121 }
122
123 gint
124 gdk_property_get (GdkWindow   *window,
125                   GdkAtom      property,
126                   GdkAtom      type,
127                   gulong       offset,
128                   gulong       length,
129                   gint         pdelete,
130                   GdkAtom     *actual_property_type,
131                   gint        *actual_format_type,
132                   gint        *actual_length,
133                   guchar     **data)
134 {
135   g_return_val_if_fail (window != NULL, FALSE);
136   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
137
138   if (GDK_WINDOW_DESTROYED (window))
139     return FALSE;
140
141   g_warning ("gdk_property_get: Not implemented");
142
143   return FALSE;
144 }
145
146 void
147 gdk_property_change (GdkWindow    *window,
148                      GdkAtom       property,
149                      GdkAtom       type,
150                      gint          format,
151                      GdkPropMode   mode,
152                      const guchar *data,
153                      gint          nelements)
154 {
155   HGLOBAL hdata;
156   UINT cf = 0;
157   gint i, size, nchars;
158   gchar *prop_name, *type_name;
159   guchar *ucptr, *buf = NULL;
160   wchar_t *wcptr;
161   glong wclen;
162   enum { SYSTEM_CODEPAGE, UNICODE_TEXT } method;
163   gboolean ok = TRUE;
164
165   g_return_if_fail (window != NULL);
166   g_return_if_fail (GDK_IS_WINDOW (window));
167
168   if (GDK_WINDOW_DESTROYED (window))
169     return;
170
171   GDK_NOTE (DND,
172             (prop_name = gdk_atom_name (property),
173              type_name = gdk_atom_name (type),
174              g_print ("gdk_property_change: %p %#x (%s) %#x (%s) %s %d*%d bytes: %s\n",
175                       GDK_WINDOW_HWND (window),
176                       (guint) property, prop_name,
177                       (guint) type, type_name,
178                       (mode == GDK_PROP_MODE_REPLACE ? "REPLACE" :
179                        (mode == GDK_PROP_MODE_PREPEND ? "PREPEND" :
180                         (mode == GDK_PROP_MODE_APPEND ? "APPEND" :
181                          "???"))),
182                       format, nelements,
183                       _gdk_win32_data_to_string (data, MIN (10, format*nelements/8))),
184              g_free (prop_name),
185              g_free (type_name)));
186
187   /* We should never come here for these types */
188   g_return_if_fail (type != GDK_TARGET_STRING);
189   g_return_if_fail (type != _text);
190   g_return_if_fail (type != _compound_text);
191   g_return_if_fail (type != _save_targets);
192
193   if (property == _gdk_selection_property
194       && format == 8
195       && mode == GDK_PROP_MODE_REPLACE)
196     {
197       if (type == _utf8_string)
198         {
199           if (!OpenClipboard (GDK_WINDOW_HWND (window)))
200             {
201               WIN32_API_FAILED ("OpenClipboard");
202               return;
203             }
204
205           nchars = g_utf8_strlen (data, nelements);
206
207           /* Check if only ASCII */
208           for (i = 0; i < nelements; i++)
209             if (data[i] >= 0200)
210               break;
211
212           if (i == nelements)
213             {
214               /* If only ASCII, use CF_TEXT and the data as such */
215               method = SYSTEM_CODEPAGE;
216               size = nelements;
217               for (i = 0; i < nelements; i++)
218                 if (data[i] == '\n')
219                   size++;
220               size++;
221               GDK_NOTE (DND, g_print ("... as text: %.40s\n", data));
222             }
223           else
224             {
225               /* Use CF_UNICODETEXT */
226               method = UNICODE_TEXT;
227
228               wcptr = g_utf8_to_utf16 (data, nelements, NULL, &wclen, NULL);
229
230               wclen++;          /* Terminating 0 */
231               size = wclen * 2;
232               for (i = 0; i < wclen; i++)
233                 if (wcptr[i] == '\n')
234                   size += 2;
235               GDK_NOTE (DND, g_print ("... as Unicode\n"));
236             }
237           
238           if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
239             {
240               WIN32_API_FAILED ("GlobalAlloc");
241               if (!CloseClipboard ())
242                 WIN32_API_FAILED ("CloseClipboard");
243               g_free (buf);
244               return;
245             }
246
247           ucptr = GlobalLock (hdata);
248
249           switch (method)
250             {
251             case SYSTEM_CODEPAGE:
252               cf = CF_TEXT;
253               for (i = 0; i < nelements; i++)
254                 {
255                   if (data[i] == '\n')
256                     *ucptr++ = '\r';
257                   *ucptr++ = data[i];
258                 }
259               *ucptr++ = '\0';
260               break;
261
262             case UNICODE_TEXT:
263               {
264                 wchar_t *p = (wchar_t *) ucptr;
265                 cf = CF_UNICODETEXT;
266                 for (i = 0; i < wclen; i++)
267                   {
268                     if (wcptr[i] == '\n')
269                       *p++ = '\r';
270                     *p++ = wcptr[i];
271                   }
272                 g_free (wcptr);
273               }
274               break;
275
276             default:
277               g_assert_not_reached ();
278             }
279
280           GlobalUnlock (hdata);
281           GDK_NOTE (DND, g_print ("... SetClipboardData(%s,%p)\n",
282                                   _gdk_win32_cf_to_string (cf), hdata));
283           if (ok && !SetClipboardData (cf, hdata))
284             WIN32_API_FAILED ("SetClipboardData"), ok = FALSE;
285       
286           if (!CloseClipboard ())
287             WIN32_API_FAILED ("CloseClipboard");
288         }
289       else
290         {
291           GDK_NOTE (DND, g_print ("... delayed rendering\n"));
292           /* Delayed Rendering. We can't assign hdata to the clipboard
293            * here as type may be "image/png", "image/jpg", etc.  In
294            * this case there's a further conversion afterwards.
295            */
296           _delayed_rendering_data = NULL;
297           if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, nelements > 0 ? nelements : 1)))
298             {
299               WIN32_API_FAILED ("GlobalAlloc");
300               return;
301             }
302           ucptr = GlobalLock (hdata);
303           memcpy (ucptr, data, nelements);
304           GlobalUnlock (hdata);
305           _delayed_rendering_data = hdata;
306         }
307     }
308   else
309     g_warning ("gdk_property_change: General case not implemented");
310 }
311
312 void
313 gdk_property_delete (GdkWindow *window,
314                      GdkAtom    property)
315 {
316   gchar *prop_name;
317
318   g_return_if_fail (window != NULL);
319   g_return_if_fail (GDK_IS_WINDOW (window));
320
321   GDK_NOTE (DND,
322             (prop_name = gdk_atom_name (property),
323              g_print ("gdk_property_delete: %p %#x (%s)\n",
324                       GDK_WINDOW_HWND (window),
325                       (guint) property, prop_name),
326              g_free (prop_name)));
327
328   if (property == _gdk_selection_property)
329     _gdk_selection_property_delete (window);
330   else if (property == _wm_transient_for)
331     gdk_window_set_transient_for (window, _gdk_root);
332   else
333     {
334       prop_name = gdk_atom_name (property);
335       g_warning ("gdk_property_delete: General case (%s) not implemented",
336                  prop_name);
337       g_free (prop_name);
338     }
339 }
340
341 /*
342   for reference copied from gdk/x11/gdkevents-x11.c
343
344   { "Net/DoubleClickTime", "gtk-double-click-time" },
345   { "Net/DoubleClickDistance", "gtk-double-click-distance" },
346   { "Net/DndDragThreshold", "gtk-dnd-drag-threshold" },
347   { "Gtk/CanChangeAccels", "gtk-can-change-accels" },
348   { "Gtk/ColorPalette", "gtk-color-palette" },
349   { "Gtk/FontName", "gtk-font-name" },
350   { "Gtk/IconSizes", "gtk-icon-sizes" },
351   { "Gtk/KeyThemeName", "gtk-key-theme-name" },
352   { "Gtk/ToolbarStyle", "gtk-toolbar-style" },
353   { "Gtk/ToolbarIconSize", "gtk-toolbar-icon-size" },
354   { "Gtk/IMPreeditStyle", "gtk-im-preedit-style" },
355   { "Gtk/IMStatusStyle", "gtk-im-status-style" },
356   { "Gtk/IMModule", "gtk-im-module" },
357   { "Net/CursorBlink", "gtk-cursor-blink" },
358   { "Net/CursorBlinkTime", "gtk-cursor-blink-time" },
359   { "Net/ThemeName", "gtk-theme-name" },
360   { "Net/IconThemeName", "gtk-icon-theme-name" },
361   { "Gtk/ButtonImages", "gtk-button-images" },
362   { "Gtk/MenuImages", "gtk-menu-images" },
363   { "Xft/Antialias", "gtk-xft-antialias" },
364   { "Xft/Hinting", "gtk-xft-hinting" },
365   { "Xft/HintStyle", "gtk-xft-hintstyle" },
366   { "Xft/RGBA", "gtk-xft-rgba" },
367   { "Xft/DPI", "gtk-xft-dpi" },
368
369   // more spread in gtk sources
370   gtk-entry-select-on-focus
371   gtk-cursor-blink
372   gtk-cursor-blink-time
373   gtk-split-cursor
374
375 */
376 gboolean
377 gdk_screen_get_setting (GdkScreen   *screen,
378                         const gchar *name,
379                         GValue      *value)
380 {
381   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
382
383   /*
384    * XXX : if these values get changed through the Windoze UI the
385    *       respective gdk_events are not generated yet.
386    */
387   if (strcmp ("gtk-theme-name", name) == 0) 
388     {
389       g_value_set_string (value, "ms-windows");
390     }
391   else if (strcmp ("gtk-double-click-time", name) == 0)
392     {
393       gint i = GetDoubleClickTime ();
394       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
395       g_value_set_int (value, i);
396       return TRUE;
397     }
398   else if (strcmp ("gtk-double-click-distance", name) == 0)
399     {
400       gint i = MAX(GetSystemMetrics (SM_CXDOUBLECLK), GetSystemMetrics (SM_CYDOUBLECLK));
401       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
402       g_value_set_int (value, i);
403       return TRUE;
404     }
405   else if (strcmp ("gtk-dnd-drag-threshold", name) == 0)
406     {
407       gint i = MAX(GetSystemMetrics (SM_CXDRAG), GetSystemMetrics (SM_CYDRAG));
408       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
409       g_value_set_int (value, i);
410       return TRUE;
411     }
412   else if (strcmp ("gtk-split-cursor", name) == 0)
413     {
414       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : FALSE\n", name));
415       g_value_set_boolean (value, FALSE);
416       return TRUE;
417     }
418   else if (strcmp ("gtk-alternative-button-order", name) == 0)
419     {
420       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : TRUE\n", name));
421       g_value_set_boolean (value, TRUE);
422       return TRUE;
423     }
424   else if (strcmp ("gtk-alternative-sort-arrows", name) == 0)
425     {
426       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : TRUE\n", name));
427       g_value_set_boolean (value, TRUE);
428       return TRUE;
429     }
430 #if 0
431   /*
432    * With 'MS Sans Serif' as windows menu font (default on win98se) you'll get a 
433    * bunch of :
434    *   WARNING **: Couldn't load font "MS Sans Serif 8" falling back to "Sans 8"
435    * at least with testfilechooser (regardless of the bitmap check below)
436    * so just disabling this code seems to be the best we can do --hb
437    */
438   else if (strcmp ("gtk-font-name", name) == 0)
439     {
440       NONCLIENTMETRICS ncm;
441       ncm.cbSize = sizeof(NONCLIENTMETRICS);
442       if (SystemParametersInfo (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, FALSE))
443         {
444           /* Pango finally uses GetDeviceCaps to scale, we use simple
445            * approximation here.
446            */
447           int nHeight = (0 > ncm.lfMenuFont.lfHeight ? -3*ncm.lfMenuFont.lfHeight/4 : 10);
448           if (OUT_STRING_PRECIS == ncm.lfMenuFont.lfOutPrecision)
449             GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) : ignoring bitmap font '%s'\n", 
450                                    name, ncm.lfMenuFont.lfFaceName));
451           else if (ncm.lfMenuFont.lfFaceName && strlen(ncm.lfMenuFont.lfFaceName) > 0 &&
452                    /* Avoid issues like those described in bug #135098 */
453                    g_utf8_validate (ncm.lfMenuFont.lfFaceName, -1, NULL))
454             {
455               char* s = g_strdup_printf ("%s %d", ncm.lfMenuFont.lfFaceName, nHeight);
456               GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) : %s\n", name, s));
457               g_value_set_string (value, s);
458
459               g_free(s);
460               return TRUE;
461             }
462         }
463     }
464 #endif
465
466   GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) not handled\n", name));
467   return FALSE;
468 }