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 
30 #include <glib/gprintf.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <limits.h>
34 #include <io.h>
35 
36 #include "gdk.h"
37 #include "gdkregion-generic.h"
38 #include "gdkkeysyms.h"
39 #include "gdkinternals.h"
40 #include "gdkintl.h"
41 #include "gdkprivate-win32.h"
42 #include "gdkinput-win32.h"
43 
44 #include <objbase.h>
45 
46 #include <imm.h>
47 
48 static gboolean gdk_synchronize = FALSE;
49 
50 static gboolean dummy;
51 
52 const GOptionEntry _gdk_windowing_args[] = {
53   { "sync", 0, 0, G_OPTION_ARG_NONE, &gdk_synchronize,
54     /* Description of --sync in --help output */              N_("Don't batch GDI requests"), NULL },
55   { "no-wintab", 0, 0, G_OPTION_ARG_NONE, &_gdk_input_ignore_wintab,
56     /* Description of --no-wintab in --help output */         N_("Don't use the Wintab API for tablet support"), NULL },
57   { "ignore-wintab", 0, 0, G_OPTION_ARG_NONE, &_gdk_input_ignore_wintab,
58     /* Description of --ignore-wintab in --help output */     N_("Same as --no-wintab"), NULL },
59   { "use-wintab", 0, 0, G_OPTION_ARG_NONE, &dummy,
60     /* Description of --use-wintab in --help output */     N_("Do use the Wintab API [default]"), NULL },
61   { "max-colors", 0, 0, G_OPTION_ARG_INT, &_gdk_max_colors,
62     /* Description of --max-colors=COLORS in --help output */ N_("Size of the palette in 8 bit mode"),
63     /* Placeholder in --max-colors=COLORS in --help output */ N_("COLORS") },
64   { NULL }
65 };
66 
67 int __stdcall
DllMain(HINSTANCE hinstDLL,DWORD dwReason,LPVOID reserved)68 DllMain (HINSTANCE hinstDLL,
69 	 DWORD     dwReason,
70 	 LPVOID    reserved)
71 {
72   _gdk_dll_hinstance = hinstDLL;
73 
74   return TRUE;
75 }
76 
77 void
_gdk_windowing_init(void)78 _gdk_windowing_init (void)
79 {
80   gchar buf[10];
81 
82   if (getenv ("GDK_IGNORE_WINTAB") != NULL)
83     _gdk_input_ignore_wintab = TRUE;
84   else if (getenv ("GDK_USE_WINTAB") != NULL)
85     _gdk_input_ignore_wintab = FALSE;
86 
87   if (gdk_synchronize)
88     GdiSetBatchLimit (1);
89 
90   _gdk_app_hmodule = GetModuleHandle (NULL);
91   _gdk_display_hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);
92   _gdk_input_locale = GetKeyboardLayout (0);
93   _gdk_win32_keymap_set_active_layout (GDK_WIN32_KEYMAP (gdk_keymap_get_default ()), _gdk_input_locale);
94   _gdk_input_locale_is_ime = ImmIsIME (_gdk_input_locale);
95   GetLocaleInfo (MAKELCID (LOWORD (_gdk_input_locale), SORT_DEFAULT),
96 		 LOCALE_IDEFAULTANSICODEPAGE,
97 		 buf, sizeof (buf));
98   _gdk_input_codepage = atoi (buf);
99   GDK_NOTE (EVENTS, g_print ("input_locale:%p, codepage:%d\n",
100 			     _gdk_input_locale, _gdk_input_codepage));
101 
102   CoInitialize (NULL);
103 
104   _gdk_selection = gdk_atom_intern_static_string ("GDK_SELECTION");
105   _wm_transient_for = gdk_atom_intern_static_string ("WM_TRANSIENT_FOR");
106   _targets = gdk_atom_intern_static_string ("TARGETS");
107   _delete = gdk_atom_intern_static_string ("DELETE");
108   _save_targets = gdk_atom_intern_static_string ("SAVE_TARGETS");
109   _utf8_string = gdk_atom_intern_static_string ("UTF8_STRING");
110   _text = gdk_atom_intern_static_string ("TEXT");
111   _compound_text = gdk_atom_intern_static_string ("COMPOUND_TEXT");
112   _text_uri_list = gdk_atom_intern_static_string ("text/uri-list");
113   _text_html = gdk_atom_intern_static_string ("text/html");
114   _image_png = gdk_atom_intern_static_string ("image/png");
115   _image_jpeg = gdk_atom_intern_static_string ("image/jpeg");
116   _image_bmp = gdk_atom_intern_static_string ("image/bmp");
117   _image_gif = gdk_atom_intern_static_string ("image/gif");
118 
119   _local_dnd = gdk_atom_intern_static_string ("LocalDndSelection");
120   _gdk_win32_dropfiles = gdk_atom_intern_static_string ("DROPFILES_DND");
121   _gdk_ole2_dnd = gdk_atom_intern_static_string ("OLE2_DND");
122 
123   /* MS Office 2007, at least, offers images in common file formats
124    * using clipboard format names like "PNG" and "JFIF". So we follow
125    * the lead and map the GDK target name "image/png" to the clipboard
126    * format name "PNG" etc.
127    */
128   _cf_png = RegisterClipboardFormat ("PNG");
129   _cf_jfif = RegisterClipboardFormat ("JFIF");
130   _cf_gif = RegisterClipboardFormat ("GIF");
131 
132   _cf_url = RegisterClipboardFormat ("UniformResourceLocatorW");
133   _cf_html_format = RegisterClipboardFormat ("HTML Format");
134   _cf_text_html = RegisterClipboardFormat ("text/html");
135 
136   _gdk_win32_selection_init ();
137 }
138 
139 void
_gdk_win32_api_failed(const gchar * where,const gchar * api)140 _gdk_win32_api_failed (const gchar *where,
141 		      const gchar *api)
142 {
143   gchar *msg = g_win32_error_message (GetLastError ());
144   g_warning ("%s: %s failed: %s", where, api, msg);
145   g_free (msg);
146 }
147 
148 void
_gdk_other_api_failed(const gchar * where,const gchar * api)149 _gdk_other_api_failed (const gchar *where,
150 		      const gchar *api)
151 {
152   g_warning ("%s: %s failed", where, api);
153 }
154 
155 void
gdk_set_use_xshm(gboolean use_xshm)156 gdk_set_use_xshm (gboolean use_xshm)
157 {
158   /* Always on */
159 }
160 
161 gboolean
gdk_get_use_xshm(void)162 gdk_get_use_xshm (void)
163 {
164   return TRUE;
165 }
166 
167 gint
gdk_screen_get_width(GdkScreen * screen)168 gdk_screen_get_width (GdkScreen *screen)
169 {
170   return GDK_WINDOW_OBJECT (_gdk_root)->width;
171 }
172 
173 gint
gdk_screen_get_height(GdkScreen * screen)174 gdk_screen_get_height (GdkScreen *screen)
175 {
176   return GDK_WINDOW_OBJECT (_gdk_root)->height;
177 }
178 gint
gdk_screen_get_width_mm(GdkScreen * screen)179 gdk_screen_get_width_mm (GdkScreen *screen)
180 {
181   return (double) gdk_screen_get_width (screen) / GetDeviceCaps (_gdk_display_hdc, LOGPIXELSX) * 25.4;
182 }
183 
184 gint
gdk_screen_get_height_mm(GdkScreen * screen)185 gdk_screen_get_height_mm (GdkScreen *screen)
186 {
187   return (double) gdk_screen_get_height (screen) / GetDeviceCaps (_gdk_display_hdc, LOGPIXELSY) * 25.4;
188 }
189 
190 void
_gdk_windowing_display_set_sm_client_id(GdkDisplay * display,const gchar * sm_client_id)191 _gdk_windowing_display_set_sm_client_id (GdkDisplay  *display,
192 					 const gchar *sm_client_id)
193 {
194   g_warning("gdk_set_sm_client_id %s", sm_client_id ? sm_client_id : "NULL");
195 }
196 
197 void
gdk_display_beep(GdkDisplay * display)198 gdk_display_beep (GdkDisplay *display)
199 {
200   g_return_if_fail (display == gdk_display_get_default());
201   if (!MessageBeep (-1))
202     Beep (1000, 50);
203 }
204 
205 void
_gdk_windowing_exit(void)206 _gdk_windowing_exit (void)
207 {
208   _gdk_win32_dnd_exit ();
209   CoUninitialize ();
210   DeleteDC (_gdk_display_hdc);
211   _gdk_display_hdc = NULL;
212 }
213 
214 gchar *
gdk_get_display(void)215 gdk_get_display (void)
216 {
217   return g_strdup (gdk_display_get_name (gdk_display_get_default ()));
218 }
219 
220 void
gdk_error_trap_push(void)221 gdk_error_trap_push (void)
222 {
223 }
224 
225 gint
gdk_error_trap_pop(void)226 gdk_error_trap_pop (void)
227 {
228   return 0;
229 }
230 
231 void
gdk_notify_startup_complete(void)232 gdk_notify_startup_complete (void)
233 {
234 }
235 
236 void
gdk_notify_startup_complete_with_id(const gchar * startup_id)237 gdk_notify_startup_complete_with_id (const gchar* startup_id)
238 {
239 }
240 
241 void
gdk_window_set_startup_id(GdkWindow * window,const gchar * startup_id)242 gdk_window_set_startup_id (GdkWindow   *window,
243 			   const gchar *startup_id)
244 {
245 }
246 
247 #ifdef G_ENABLE_DEBUG
248 
249 /*
250  * Like g_strdup_printf, but to a static buffer. Return value does not
251  * have to be g_free()d. The buffer is of bounded size and reused
252  * cyclically. Thus the return value is valid only until that part of
253  * the buffer happens to get reused. This doesn't matter as this
254  * function's return value is used in debugging output right after the call,
255  * and the return value isn't used after that.
256  */
257 static gchar *
static_printf(const gchar * format,...)258 static_printf (const gchar *format,
259 	       ...)
260 {
261   static gchar buf[10000];
262   gchar *msg;
263   static gchar *bufp = buf;
264   gchar *retval;
265   va_list args;
266 
267   va_start (args, format);
268   msg = g_strdup_vprintf (format, args);
269   va_end (args);
270 
271   g_assert (strlen (msg) < sizeof (buf));
272 
273   if (bufp + strlen (msg) + 1 > buf + sizeof (buf))
274     bufp = buf;
275   retval = bufp;
276 
277   strcpy (bufp, msg);
278   bufp += strlen (msg) + 1;
279   g_free (msg);
280 
281   return retval;
282 }
283 
284 gchar *
_gdk_win32_color_to_string(const GdkColor * color)285 _gdk_win32_color_to_string (const GdkColor *color)
286 {
287   return static_printf ("(%.04x,%.04x,%.04x):%.06x",
288 			color->red, color->green,
289 			color->blue, color->pixel);
290 }
291 
292 void
_gdk_win32_print_paletteentries(const PALETTEENTRY * pep,const int nentries)293 _gdk_win32_print_paletteentries (const PALETTEENTRY *pep,
294 				const int           nentries)
295 {
296   char buf[20];
297   int i;
298 
299   for (i = 0; i < nentries; i++)
300     g_print ("  %3d %02x:  %02x %02x %02x%s\n",
301 	     i, i,
302 	     pep[i].peRed, pep[i].peGreen, pep[i].peBlue,
303 	     (pep[i].peFlags == 0 ? "" :
304 	      (pep[i].peFlags == PC_EXPLICIT ? " PC_EXPLICIT" :
305 	       (pep[i].peFlags == PC_NOCOLLAPSE ? " PC_NOCOLLAPSE" :
306 		(pep[i].peFlags == PC_RESERVED ? " PC_RESERVED" :
307 		 (g_sprintf (buf, " %d", pep[i].peFlags), buf))))));
308 }
309 
310 void
_gdk_win32_print_system_palette(void)311 _gdk_win32_print_system_palette (void)
312 {
313   PALETTEENTRY *pe;
314   int k;
315 
316   k = GetSystemPaletteEntries (_gdk_display_hdc, 0, 0, NULL);
317   pe = g_new (PALETTEENTRY, k);
318   k = GetSystemPaletteEntries (_gdk_display_hdc, 0, k, pe);
319 
320   if (!k)
321     g_print ("GetSystemPaletteEntries failed: %s\n",
322 	     g_win32_error_message (GetLastError ()));
323   else
324     {
325       g_print ("System palette: %d entries\n", k);
326       _gdk_win32_print_paletteentries (pe, k);
327     }
328   g_free (pe);
329 }
330 
331 static gint
palette_size(HPALETTE hpal)332 palette_size (HPALETTE hpal)
333 {
334   WORD npal = 0;
335 
336   if (!GetObject (hpal, sizeof (npal), &npal))
337     WIN32_GDI_FAILED ("GetObject (HPALETTE)");
338 
339   return npal;
340 }
341 
342 void
_gdk_win32_print_hpalette(HPALETTE hpal)343 _gdk_win32_print_hpalette (HPALETTE hpal)
344 {
345   PALETTEENTRY *pe;
346   gint n, npal;
347 
348   npal = palette_size (hpal);
349   pe = g_new (PALETTEENTRY, npal);
350   n = GetPaletteEntries (hpal, 0, npal, pe);
351 
352   if (!n)
353     g_print ("HPALETTE %p: GetPaletteEntries failed: %s\n",
354 	     hpal, g_win32_error_message (GetLastError ()));
355   else
356     {
357       g_print ("HPALETTE %p: %d (%d) entries\n", hpal, n, npal);
358       _gdk_win32_print_paletteentries (pe, n);
359     }
360   g_free (pe);
361 }
362 
363 void
_gdk_win32_print_dc(HDC hdc)364 _gdk_win32_print_dc (HDC hdc)
365 {
366   HGDIOBJ obj;
367   LOGBRUSH logbrush;
368   EXTLOGPEN extlogpen;
369   HRGN hrgn;
370   RECT rect;
371   int flag;
372 
373   g_print ("%p:\n", hdc);
374   obj = GetCurrentObject (hdc, OBJ_BRUSH);
375   GetObject (obj, sizeof (LOGBRUSH), &logbrush);
376   g_print ("brush: %s color=%06lx hatch=%p\n",
377 	   _gdk_win32_lbstyle_to_string (logbrush.lbStyle),
378 	   logbrush.lbColor, (gpointer) logbrush.lbHatch);
379   obj = GetCurrentObject (hdc, OBJ_PEN);
380   GetObject (obj, sizeof (EXTLOGPEN), &extlogpen);
381   g_print ("pen: %s %s %s %s w=%d %s\n",
382 	   _gdk_win32_pstype_to_string (extlogpen.elpPenStyle),
383 	   _gdk_win32_psstyle_to_string (extlogpen.elpPenStyle),
384 	   _gdk_win32_psendcap_to_string (extlogpen.elpPenStyle),
385 	   _gdk_win32_psjoin_to_string (extlogpen.elpPenStyle),
386 	   (int) extlogpen.elpWidth,
387 	   _gdk_win32_lbstyle_to_string (extlogpen.elpBrushStyle));
388   g_print ("rop2: %s textcolor=%06lx\n",
389 	   _gdk_win32_rop2_to_string (GetROP2 (hdc)),
390 	   GetTextColor (hdc));
391   hrgn = CreateRectRgn (0, 0, 0, 0);
392   if ((flag = GetClipRgn (hdc, hrgn)) == -1)
393     WIN32_API_FAILED ("GetClipRgn");
394   else if (flag == 0)
395     g_print ("no clip region\n");
396   else if (flag == 1)
397     {
398       GetRgnBox (hrgn, &rect);
399       g_print ("clip region: %p bbox: %s\n",
400 	       hrgn, _gdk_win32_rect_to_string (&rect));
401     }
402   DeleteObject (hrgn);
403 }
404 
405 gchar *
_gdk_win32_cap_style_to_string(GdkCapStyle cap_style)406 _gdk_win32_cap_style_to_string (GdkCapStyle cap_style)
407 {
408   switch (cap_style)
409     {
410 #define CASE(x) case GDK_CAP_##x: return #x
411     CASE (NOT_LAST);
412     CASE (BUTT);
413     CASE (ROUND);
414     CASE (PROJECTING);
415 #undef CASE
416     default: return static_printf ("illegal_%d", cap_style);
417     }
418   /* NOTREACHED */
419   return NULL;
420 }
421 
422 gchar *
_gdk_win32_fill_style_to_string(GdkFill fill)423 _gdk_win32_fill_style_to_string (GdkFill fill)
424 {
425   switch (fill)
426     {
427 #define CASE(x) case GDK_##x: return #x
428     CASE (SOLID);
429     CASE (TILED);
430     CASE (STIPPLED);
431     CASE (OPAQUE_STIPPLED);
432 #undef CASE
433     default: return static_printf ("illegal_%d", fill);
434     }
435   /* NOTREACHED */
436   return NULL;
437 }
438 
439 gchar *
_gdk_win32_function_to_string(GdkFunction function)440 _gdk_win32_function_to_string (GdkFunction function)
441 {
442   switch (function)
443     {
444 #define CASE(x) case GDK_##x: return #x
445     CASE (COPY);
446     CASE (INVERT);
447     CASE (XOR);
448     CASE (CLEAR);
449     CASE (AND);
450     CASE (AND_REVERSE);
451     CASE (AND_INVERT);
452     CASE (NOOP);
453     CASE (OR);
454     CASE (EQUIV);
455     CASE (OR_REVERSE);
456     CASE (COPY_INVERT);
457     CASE (OR_INVERT);
458     CASE (NAND);
459     CASE (SET);
460 #undef CASE
461     default: return static_printf ("illegal_%d", function);
462     }
463   /* NOTREACHED */
464   return NULL;
465 }
466 
467 gchar *
_gdk_win32_join_style_to_string(GdkJoinStyle join_style)468 _gdk_win32_join_style_to_string (GdkJoinStyle join_style)
469 {
470   switch (join_style)
471     {
472 #define CASE(x) case GDK_JOIN_##x: return #x
473     CASE (MITER);
474     CASE (ROUND);
475     CASE (BEVEL);
476 #undef CASE
477     default: return static_printf ("illegal_%d", join_style);
478     }
479   /* NOTREACHED */
480   return NULL;
481 }
482 
483 gchar *
_gdk_win32_line_style_to_string(GdkLineStyle line_style)484 _gdk_win32_line_style_to_string (GdkLineStyle line_style)
485 {
486   switch (line_style)
487     {
488 #define CASE(x) case GDK_LINE_##x: return #x
489     CASE(SOLID);
490     CASE(ON_OFF_DASH);
491     CASE(DOUBLE_DASH);
492 #undef CASE
493     default: return static_printf ("illegal_%d", line_style);
494     }
495   /* NOTREACHED */
496   return NULL;
497 }
498 
499 gchar *
_gdk_win32_drag_protocol_to_string(GdkDragProtocol protocol)500 _gdk_win32_drag_protocol_to_string (GdkDragProtocol protocol)
501 {
502   switch (protocol)
503     {
504 #define CASE(x) case GDK_DRAG_PROTO_##x: return #x
505       CASE (MOTIF);
506       CASE (XDND);
507       CASE (ROOTWIN);
508       CASE (NONE);
509       CASE (WIN32_DROPFILES);
510       CASE (OLE2);
511       CASE (LOCAL);
512 #undef CASE
513     default: return static_printf ("illegal_%d", protocol);
514     }
515   /* NOTREACHED */
516   return NULL;
517 }
518 
519 gchar *
_gdk_win32_gcvalues_mask_to_string(GdkGCValuesMask mask)520 _gdk_win32_gcvalues_mask_to_string (GdkGCValuesMask mask)
521 {
522   gchar buf[400];
523   gchar *bufp = buf;
524   gchar *s = "";
525 
526   buf[0] = '\0';
527 
528 #define BIT(x) 						\
529   if (mask & GDK_GC_##x) 				\
530     (bufp += g_sprintf (bufp, "%s" #x, s), s = "|")
531 
532   BIT (FOREGROUND);
533   BIT (BACKGROUND);
534   BIT (FONT);
535   BIT (FUNCTION);
536   BIT (FILL);
537   BIT (TILE);
538   BIT (STIPPLE);
539   BIT (CLIP_MASK);
540   BIT (SUBWINDOW);
541   BIT (TS_X_ORIGIN);
542   BIT (TS_Y_ORIGIN);
543   BIT (CLIP_X_ORIGIN);
544   BIT (CLIP_Y_ORIGIN);
545   BIT (EXPOSURES);
546   BIT (LINE_WIDTH);
547   BIT (LINE_STYLE);
548   BIT (CAP_STYLE);
549   BIT (JOIN_STYLE);
550 #undef BIT
551 
552   return static_printf ("%s", buf);
553 }
554 
555 gchar *
_gdk_win32_window_state_to_string(GdkWindowState state)556 _gdk_win32_window_state_to_string (GdkWindowState state)
557 {
558   gchar buf[100];
559   gchar *bufp = buf;
560   gchar *s = "";
561 
562   buf[0] = '\0';
563 
564 #define BIT(x)						\
565   if (state & GDK_WINDOW_STATE_ ## x)			\
566     (bufp += sprintf (bufp, "%s" #x, s), s = "|")
567 
568   /* For clarity, also show the complement of WITHDRAWN, i.e. "MAPPED" */
569   if (!(state & GDK_WINDOW_STATE_WITHDRAWN))
570     (bufp += sprintf (bufp, "MAPPED"), s = "|");
571 
572   BIT (WITHDRAWN);
573   BIT (ICONIFIED);
574   BIT (MAXIMIZED);
575   BIT (STICKY);
576 #undef BIT
577 
578   return static_printf ("%s", buf);
579 }
580 
581 gchar *
_gdk_win32_window_style_to_string(LONG style)582 _gdk_win32_window_style_to_string (LONG style)
583 {
584   gchar buf[1000];
585   gchar *bufp = buf;
586   gchar *s = "";
587 
588   buf[0] = '\0';
589 
590 #define BIT(x)						\
591   if (style & WS_ ## x)					\
592     (bufp += sprintf (bufp, "%s" #x, s), s = "|")
593 
594   /* Note that many of the WS_* macros are in face several bits.
595    * Handle just the individual bits here. Sort as in w32api's
596    * winuser.h.
597    */
598   BIT (BORDER);
599   BIT (CHILD);
600   BIT (CLIPCHILDREN);
601   BIT (CLIPSIBLINGS);
602   BIT (DISABLED);
603   BIT (DLGFRAME);
604   BIT (GROUP);
605   BIT (HSCROLL);
606   BIT (ICONIC);
607   BIT (MAXIMIZE);
608   BIT (MAXIMIZEBOX);
609   BIT (MINIMIZE);
610   BIT (MINIMIZEBOX);
611   BIT (POPUP);
612   BIT (SIZEBOX);
613   BIT (SYSMENU);
614   BIT (TABSTOP);
615   BIT (THICKFRAME);
616   BIT (VISIBLE);
617   BIT (VSCROLL);
618 #undef BIT
619 
620   return static_printf ("%s", buf);
621 }
622 
623 gchar *
_gdk_win32_window_exstyle_to_string(LONG style)624 _gdk_win32_window_exstyle_to_string (LONG style)
625 {
626   gchar buf[1000];
627   gchar *bufp = buf;
628   gchar *s = "";
629 
630   buf[0] = '\0';
631 
632 #define BIT(x)						\
633   if (style & WS_EX_ ## x)				\
634     (bufp += sprintf (bufp, "%s" #x, s), s = "|")
635 
636   /* Note that many of the WS_EX_* macros are in face several bits.
637    * Handle just the individual bits here. Sort as in w32api's
638    * winuser.h.
639    */
640   BIT (ACCEPTFILES);
641   BIT (APPWINDOW);
642   BIT (CLIENTEDGE);
643 #ifndef WS_EX_COMPOSITED
644 #  define WS_EX_COMPOSITED 0x02000000L
645 #endif
646   BIT (COMPOSITED);
647   BIT (CONTEXTHELP);
648   BIT (CONTROLPARENT);
649   BIT (DLGMODALFRAME);
650   BIT (LAYERED);
651   BIT (LAYOUTRTL);
652   BIT (LEFTSCROLLBAR);
653   BIT (MDICHILD);
654   BIT (NOACTIVATE);
655   BIT (NOINHERITLAYOUT);
656   BIT (NOPARENTNOTIFY);
657   BIT (RIGHT);
658   BIT (RTLREADING);
659   BIT (STATICEDGE);
660   BIT (TOOLWINDOW);
661   BIT (TOPMOST);
662   BIT (TRANSPARENT);
663   BIT (WINDOWEDGE);
664 #undef BIT
665 
666   return static_printf ("%s", buf);
667 }
668 
669 gchar *
_gdk_win32_window_pos_bits_to_string(UINT flags)670 _gdk_win32_window_pos_bits_to_string (UINT flags)
671 {
672   gchar buf[1000];
673   gchar *bufp = buf;
674   gchar *s = "";
675 
676   buf[0] = '\0';
677 
678 #define BIT(x)						\
679   if (flags & SWP_ ## x)				\
680     (bufp += sprintf (bufp, "%s" #x, s), s = "|")
681 
682   BIT (DRAWFRAME);
683   BIT (FRAMECHANGED);
684   BIT (HIDEWINDOW);
685   BIT (NOACTIVATE);
686   BIT (NOCOPYBITS);
687   BIT (NOMOVE);
688   BIT (NOSIZE);
689   BIT (NOREDRAW);
690   BIT (NOZORDER);
691   BIT (SHOWWINDOW);
692   BIT (NOOWNERZORDER);
693   BIT (NOSENDCHANGING);
694   BIT (DEFERERASE);
695   BIT (ASYNCWINDOWPOS);
696 #undef BIT
697 
698   return static_printf ("%s", buf);
699 }
700 
701 gchar *
_gdk_win32_drag_action_to_string(GdkDragAction actions)702 _gdk_win32_drag_action_to_string (GdkDragAction actions)
703 {
704   gchar buf[100];
705   gchar *bufp = buf;
706   gchar *s = "";
707 
708   buf[0] = '\0';
709 
710 #define BIT(x)						\
711   if (actions & GDK_ACTION_ ## x)				\
712     (bufp += sprintf (bufp, "%s" #x, s), s = "|")
713 
714   BIT (DEFAULT);
715   BIT (COPY);
716   BIT (MOVE);
717   BIT (LINK);
718   BIT (PRIVATE);
719   BIT (ASK);
720 #undef BIT
721 
722   return static_printf ("%s", buf);
723 }
724 
725 gchar *
_gdk_win32_rop2_to_string(int rop2)726 _gdk_win32_rop2_to_string (int rop2)
727 {
728   switch (rop2)
729     {
730 #define CASE(x) case R2_##x: return #x
731       CASE (BLACK);
732       CASE (COPYPEN);
733       CASE (MASKNOTPEN);
734       CASE (MASKPEN);
735       CASE (MASKPENNOT);
736       CASE (MERGENOTPEN);
737       CASE (MERGEPEN);
738       CASE (MERGEPENNOT);
739       CASE (NOP);
740       CASE (NOT);
741       CASE (NOTCOPYPEN);
742       CASE (NOTMASKPEN);
743       CASE (NOTMERGEPEN);
744       CASE (NOTXORPEN);
745       CASE (WHITE);
746       CASE (XORPEN);
747 #undef CASE
748     default: return static_printf ("illegal_%x", rop2);
749     }
750   /* NOTREACHED */
751   return NULL;
752 }
753 
754 gchar *
_gdk_win32_lbstyle_to_string(UINT brush_style)755 _gdk_win32_lbstyle_to_string (UINT brush_style)
756 {
757   switch (brush_style)
758     {
759 #define CASE(x) case BS_##x: return #x
760       CASE (DIBPATTERN);
761       CASE (DIBPATTERNPT);
762       CASE (HATCHED);
763       CASE (HOLLOW);
764       CASE (PATTERN);
765       CASE (SOLID);
766 #undef CASE
767     default: return static_printf ("illegal_%d", brush_style);
768     }
769   /* NOTREACHED */
770   return NULL;
771 }
772 
773 gchar *
_gdk_win32_pstype_to_string(DWORD pen_style)774 _gdk_win32_pstype_to_string (DWORD pen_style)
775 {
776   switch (pen_style & PS_TYPE_MASK)
777     {
778     case PS_GEOMETRIC: return "GEOMETRIC";
779     case PS_COSMETIC: return "COSMETIC";
780     default: return static_printf ("illegal_%d", pen_style & PS_TYPE_MASK);
781     }
782   /* NOTREACHED */
783   return NULL;
784 }
785 
786 gchar *
_gdk_win32_psstyle_to_string(DWORD pen_style)787 _gdk_win32_psstyle_to_string (DWORD pen_style)
788 {
789   switch (pen_style & PS_STYLE_MASK)
790     {
791 #define CASE(x) case PS_##x: return #x
792       CASE (ALTERNATE);
793       CASE (SOLID);
794       CASE (DASH);
795       CASE (DOT);
796       CASE (DASHDOT);
797       CASE (DASHDOTDOT);
798       CASE (NULL);
799       CASE (USERSTYLE);
800       CASE (INSIDEFRAME);
801 #undef CASE
802     default: return static_printf ("illegal_%d", pen_style & PS_STYLE_MASK);
803     }
804   /* NOTREACHED */
805   return NULL;
806 }
807 
808 gchar *
_gdk_win32_psendcap_to_string(DWORD pen_style)809 _gdk_win32_psendcap_to_string (DWORD pen_style)
810 {
811   switch (pen_style & PS_ENDCAP_MASK)
812     {
813 #define CASE(x) case PS_ENDCAP_##x: return #x
814       CASE (ROUND);
815       CASE (SQUARE);
816       CASE (FLAT);
817 #undef CASE
818     default: return static_printf ("illegal_%d", pen_style & PS_ENDCAP_MASK);
819     }
820   /* NOTREACHED */
821   return NULL;
822 }
823 
824 gchar *
_gdk_win32_psjoin_to_string(DWORD pen_style)825 _gdk_win32_psjoin_to_string (DWORD pen_style)
826 {
827   switch (pen_style & PS_JOIN_MASK)
828     {
829 #define CASE(x) case PS_JOIN_##x: return #x
830       CASE (ROUND);
831       CASE (BEVEL);
832       CASE (MITER);
833 #undef CASE
834     default: return static_printf ("illegal_%d", pen_style & PS_JOIN_MASK);
835     }
836   /* NOTREACHED */
837   return NULL;
838 }
839 
840 gchar *
_gdk_win32_message_to_string(UINT msg)841 _gdk_win32_message_to_string (UINT msg)
842 {
843   switch (msg)
844     {
845 #define CASE(x) case x: return #x
846       CASE (WM_NULL);
847       CASE (WM_CREATE);
848       CASE (WM_DESTROY);
849       CASE (WM_MOVE);
850       CASE (WM_SIZE);
851       CASE (WM_ACTIVATE);
852       CASE (WM_SETFOCUS);
853       CASE (WM_KILLFOCUS);
854       CASE (WM_ENABLE);
855       CASE (WM_SETREDRAW);
856       CASE (WM_SETTEXT);
857       CASE (WM_GETTEXT);
858       CASE (WM_GETTEXTLENGTH);
859       CASE (WM_PAINT);
860       CASE (WM_CLOSE);
861       CASE (WM_QUERYENDSESSION);
862       CASE (WM_QUERYOPEN);
863       CASE (WM_ENDSESSION);
864       CASE (WM_QUIT);
865       CASE (WM_ERASEBKGND);
866       CASE (WM_SYSCOLORCHANGE);
867       CASE (WM_SHOWWINDOW);
868       CASE (WM_WININICHANGE);
869       CASE (WM_DEVMODECHANGE);
870       CASE (WM_ACTIVATEAPP);
871       CASE (WM_FONTCHANGE);
872       CASE (WM_TIMECHANGE);
873       CASE (WM_CANCELMODE);
874       CASE (WM_SETCURSOR);
875       CASE (WM_MOUSEACTIVATE);
876       CASE (WM_CHILDACTIVATE);
877       CASE (WM_QUEUESYNC);
878       CASE (WM_GETMINMAXINFO);
879       CASE (WM_PAINTICON);
880       CASE (WM_ICONERASEBKGND);
881       CASE (WM_NEXTDLGCTL);
882       CASE (WM_SPOOLERSTATUS);
883       CASE (WM_DRAWITEM);
884       CASE (WM_MEASUREITEM);
885       CASE (WM_DELETEITEM);
886       CASE (WM_VKEYTOITEM);
887       CASE (WM_CHARTOITEM);
888       CASE (WM_SETFONT);
889       CASE (WM_GETFONT);
890       CASE (WM_SETHOTKEY);
891       CASE (WM_GETHOTKEY);
892       CASE (WM_QUERYDRAGICON);
893       CASE (WM_COMPAREITEM);
894       CASE (WM_GETOBJECT);
895       CASE (WM_COMPACTING);
896       CASE (WM_WINDOWPOSCHANGING);
897       CASE (WM_WINDOWPOSCHANGED);
898       CASE (WM_POWER);
899       CASE (WM_COPYDATA);
900       CASE (WM_CANCELJOURNAL);
901       CASE (WM_NOTIFY);
902       CASE (WM_INPUTLANGCHANGEREQUEST);
903       CASE (WM_INPUTLANGCHANGE);
904       CASE (WM_TCARD);
905       CASE (WM_HELP);
906       CASE (WM_USERCHANGED);
907       CASE (WM_NOTIFYFORMAT);
908       CASE (WM_CONTEXTMENU);
909       CASE (WM_STYLECHANGING);
910       CASE (WM_STYLECHANGED);
911       CASE (WM_DISPLAYCHANGE);
912       CASE (WM_GETICON);
913       CASE (WM_SETICON);
914       CASE (WM_NCCREATE);
915       CASE (WM_NCDESTROY);
916       CASE (WM_NCCALCSIZE);
917       CASE (WM_NCHITTEST);
918       CASE (WM_NCPAINT);
919       CASE (WM_NCACTIVATE);
920       CASE (WM_GETDLGCODE);
921       CASE (WM_SYNCPAINT);
922       CASE (WM_NCMOUSEMOVE);
923       CASE (WM_NCLBUTTONDOWN);
924       CASE (WM_NCLBUTTONUP);
925       CASE (WM_NCLBUTTONDBLCLK);
926       CASE (WM_NCRBUTTONDOWN);
927       CASE (WM_NCRBUTTONUP);
928       CASE (WM_NCRBUTTONDBLCLK);
929       CASE (WM_NCMBUTTONDOWN);
930       CASE (WM_NCMBUTTONUP);
931       CASE (WM_NCMBUTTONDBLCLK);
932       CASE (WM_NCXBUTTONDOWN);
933       CASE (WM_NCXBUTTONUP);
934       CASE (WM_NCXBUTTONDBLCLK);
935       CASE (WM_KEYDOWN);
936       CASE (WM_KEYUP);
937       CASE (WM_CHAR);
938       CASE (WM_DEADCHAR);
939       CASE (WM_SYSKEYDOWN);
940       CASE (WM_SYSKEYUP);
941       CASE (WM_SYSCHAR);
942       CASE (WM_SYSDEADCHAR);
943       CASE (WM_KEYLAST);
944       CASE (WM_IME_STARTCOMPOSITION);
945       CASE (WM_IME_ENDCOMPOSITION);
946       CASE (WM_IME_COMPOSITION);
947       CASE (WM_INITDIALOG);
948       CASE (WM_COMMAND);
949       CASE (WM_SYSCOMMAND);
950       CASE (WM_TIMER);
951       CASE (WM_HSCROLL);
952       CASE (WM_VSCROLL);
953       CASE (WM_INITMENU);
954       CASE (WM_INITMENUPOPUP);
955       CASE (WM_MENUSELECT);
956       CASE (WM_MENUCHAR);
957       CASE (WM_ENTERIDLE);
958       CASE (WM_MENURBUTTONUP);
959       CASE (WM_MENUDRAG);
960       CASE (WM_MENUGETOBJECT);
961       CASE (WM_UNINITMENUPOPUP);
962       CASE (WM_MENUCOMMAND);
963       CASE (WM_CHANGEUISTATE);
964       CASE (WM_UPDATEUISTATE);
965       CASE (WM_QUERYUISTATE);
966       CASE (WM_CTLCOLORMSGBOX);
967       CASE (WM_CTLCOLOREDIT);
968       CASE (WM_CTLCOLORLISTBOX);
969       CASE (WM_CTLCOLORBTN);
970       CASE (WM_CTLCOLORDLG);
971       CASE (WM_CTLCOLORSCROLLBAR);
972       CASE (WM_CTLCOLORSTATIC);
973       CASE (WM_MOUSEMOVE);
974       CASE (WM_LBUTTONDOWN);
975       CASE (WM_LBUTTONUP);
976       CASE (WM_LBUTTONDBLCLK);
977       CASE (WM_RBUTTONDOWN);
978       CASE (WM_RBUTTONUP);
979       CASE (WM_RBUTTONDBLCLK);
980       CASE (WM_MBUTTONDOWN);
981       CASE (WM_MBUTTONUP);
982       CASE (WM_MBUTTONDBLCLK);
983       CASE (WM_MOUSEWHEEL);
984       CASE (WM_MOUSEHWHEEL);
985       CASE (WM_XBUTTONDOWN);
986       CASE (WM_XBUTTONUP);
987       CASE (WM_XBUTTONDBLCLK);
988       CASE (WM_PARENTNOTIFY);
989       CASE (WM_ENTERMENULOOP);
990       CASE (WM_EXITMENULOOP);
991       CASE (WM_NEXTMENU);
992       CASE (WM_SIZING);
993       CASE (WM_CAPTURECHANGED);
994       CASE (WM_MOVING);
995       CASE (WM_POWERBROADCAST);
996       CASE (WM_DEVICECHANGE);
997       CASE (WM_MDICREATE);
998       CASE (WM_MDIDESTROY);
999       CASE (WM_MDIACTIVATE);
1000       CASE (WM_MDIRESTORE);
1001       CASE (WM_MDINEXT);
1002       CASE (WM_MDIMAXIMIZE);
1003       CASE (WM_MDITILE);
1004       CASE (WM_MDICASCADE);
1005       CASE (WM_MDIICONARRANGE);
1006       CASE (WM_MDIGETACTIVE);
1007       CASE (WM_MDISETMENU);
1008       CASE (WM_ENTERSIZEMOVE);
1009       CASE (WM_EXITSIZEMOVE);
1010       CASE (WM_DROPFILES);
1011       CASE (WM_MDIREFRESHMENU);
1012       CASE (WM_IME_SETCONTEXT);
1013       CASE (WM_IME_NOTIFY);
1014       CASE (WM_IME_CONTROL);
1015       CASE (WM_IME_COMPOSITIONFULL);
1016       CASE (WM_IME_SELECT);
1017       CASE (WM_IME_CHAR);
1018       CASE (WM_IME_REQUEST);
1019       CASE (WM_IME_KEYDOWN);
1020       CASE (WM_IME_KEYUP);
1021       CASE (WM_MOUSEHOVER);
1022       CASE (WM_MOUSELEAVE);
1023       CASE (WM_NCMOUSEHOVER);
1024       CASE (WM_NCMOUSELEAVE);
1025       CASE (WM_CUT);
1026       CASE (WM_COPY);
1027       CASE (WM_PASTE);
1028       CASE (WM_CLEAR);
1029       CASE (WM_UNDO);
1030       CASE (WM_RENDERFORMAT);
1031       CASE (WM_RENDERALLFORMATS);
1032       CASE (WM_DESTROYCLIPBOARD);
1033       CASE (WM_DRAWCLIPBOARD);
1034       CASE (WM_PAINTCLIPBOARD);
1035       CASE (WM_VSCROLLCLIPBOARD);
1036       CASE (WM_SIZECLIPBOARD);
1037       CASE (WM_ASKCBFORMATNAME);
1038       CASE (WM_CHANGECBCHAIN);
1039       CASE (WM_HSCROLLCLIPBOARD);
1040       CASE (WM_QUERYNEWPALETTE);
1041       CASE (WM_PALETTEISCHANGING);
1042       CASE (WM_PALETTECHANGED);
1043       CASE (WM_HOTKEY);
1044       CASE (WM_PRINT);
1045       CASE (WM_PRINTCLIENT);
1046       CASE (WM_APPCOMMAND);
1047       CASE (WM_HANDHELDFIRST);
1048       CASE (WM_HANDHELDLAST);
1049       CASE (WM_AFXFIRST);
1050       CASE (WM_AFXLAST);
1051       CASE (WM_PENWINFIRST);
1052       CASE (WM_PENWINLAST);
1053       CASE (WM_APP);
1054       CASE (WT_PACKET);
1055       CASE (WT_CSRCHANGE);
1056       CASE (WT_PROXIMITY);
1057 #undef CASE
1058     default:
1059       if (msg >= WM_HANDHELDFIRST && msg <= WM_HANDHELDLAST)
1060 	return static_printf ("WM_HANDHELDFIRST+%d", msg - WM_HANDHELDFIRST);
1061       else if (msg >= WM_AFXFIRST && msg <= WM_AFXLAST)
1062 	return static_printf ("WM_AFXFIRST+%d", msg - WM_AFXFIRST);
1063       else if (msg >= WM_PENWINFIRST && msg <= WM_PENWINLAST)
1064 	return static_printf ("WM_PENWINFIRST+%d", msg - WM_PENWINFIRST);
1065       else if (msg >= WM_USER && msg <= 0x7FFF)
1066 	return static_printf ("WM_USER+%d", msg - WM_USER);
1067       else if (msg >= 0xC000 && msg <= 0xFFFF)
1068 	return static_printf ("reg-%#x", msg);
1069       else
1070 	return static_printf ("unk-%#x", msg);
1071     }
1072   /* NOTREACHED */
1073   return NULL;
1074 }
1075 
1076 gchar *
_gdk_win32_key_to_string(LONG lParam)1077 _gdk_win32_key_to_string (LONG lParam)
1078 {
1079   char buf[100];
1080   gchar *keyname_utf8;
1081 
1082   if (GetKeyNameText (lParam, buf, sizeof (buf)) &&
1083       (keyname_utf8 = g_locale_to_utf8 (buf, -1, NULL, NULL, NULL)) != NULL)
1084     {
1085       gchar *retval = static_printf ("%s", keyname_utf8);
1086 
1087       g_free (keyname_utf8);
1088 
1089       return retval;
1090     }
1091 
1092   return static_printf ("unk-%#lx", lParam);
1093 }
1094 
1095 gchar *
_gdk_win32_cf_to_string(UINT format)1096 _gdk_win32_cf_to_string (UINT format)
1097 {
1098   char buf[100];
1099 
1100   switch (format)
1101     {
1102 #define CASE(x) case CF_##x: return "CF_" #x
1103       CASE (BITMAP);
1104       CASE (DIB);
1105       CASE (DIBV5);
1106       CASE (DIF);
1107       CASE (DSPBITMAP);
1108       CASE (DSPENHMETAFILE);
1109       CASE (DSPMETAFILEPICT);
1110       CASE (DSPTEXT);
1111       CASE (ENHMETAFILE);
1112       CASE (HDROP);
1113       CASE (LOCALE);
1114       CASE (METAFILEPICT);
1115       CASE (OEMTEXT);
1116       CASE (OWNERDISPLAY);
1117       CASE (PALETTE);
1118       CASE (PENDATA);
1119       CASE (RIFF);
1120       CASE (SYLK);
1121       CASE (TEXT);
1122       CASE (WAVE);
1123       CASE (TIFF);
1124       CASE (UNICODETEXT);
1125     default:
1126       if (format >= CF_GDIOBJFIRST &&
1127 	  format <= CF_GDIOBJLAST)
1128 	return static_printf ("CF_GDIOBJ%d", format - CF_GDIOBJFIRST);
1129       if (format >= CF_PRIVATEFIRST &&
1130 	  format <= CF_PRIVATELAST)
1131 	return static_printf ("CF_PRIVATE%d", format - CF_PRIVATEFIRST);
1132       if (GetClipboardFormatName (format, buf, sizeof (buf)))
1133 	return static_printf ("'%s'", buf);
1134       else
1135 	return static_printf ("unk-%#lx", format);
1136     }
1137 }
1138 
1139 gchar *
_gdk_win32_data_to_string(const guchar * data,int nbytes)1140 _gdk_win32_data_to_string (const guchar *data,
1141 			   int           nbytes)
1142 {
1143   GString *s = g_string_new ("");
1144   int i;
1145   gchar *retval;
1146 
1147   for (i = 0; i < nbytes; i++)
1148     if (data[i] >=' ' && data[i] <= '~')
1149       g_string_append_printf (s, "%c  ", data[i]);
1150     else
1151       g_string_append_printf (s, "%02X ", data[i]);
1152 
1153   retval = static_printf ("%s", s->str);
1154   g_string_free (s, TRUE);
1155 
1156   return retval;
1157 }
1158 
1159 gchar *
_gdk_win32_rect_to_string(const RECT * rect)1160 _gdk_win32_rect_to_string (const RECT *rect)
1161 {
1162   return static_printf ("%ldx%ld@%+ld%+ld",
1163 			(rect->right - rect->left), (rect->bottom - rect->top),
1164 			rect->left, rect->top);
1165 }
1166 
1167 gchar *
_gdk_win32_gdkrectangle_to_string(const GdkRectangle * rect)1168 _gdk_win32_gdkrectangle_to_string (const GdkRectangle *rect)
1169 {
1170   return static_printf ("%dx%d@%+d%+d",
1171 			rect->width, rect->height,
1172 			rect->x, rect->y);
1173 }
1174 
1175 gchar *
_gdk_win32_gdkregion_to_string(const GdkRegion * rgn)1176 _gdk_win32_gdkregion_to_string (const GdkRegion *rgn)
1177 {
1178   return static_printf ("%dx%d@%+d%+d",
1179 			(rgn->extents.x2 - rgn->extents.x1),
1180 			(rgn->extents.y2 - rgn->extents.y1),
1181 			rgn->extents.x1, rgn->extents.y1);
1182 }
1183 
1184 gchar *
_gdk_win32_drawable_description(GdkDrawable * d)1185 _gdk_win32_drawable_description (GdkDrawable *d)
1186 {
1187   gint width, height, depth;
1188 
1189   g_return_val_if_fail (GDK_IS_DRAWABLE (d), NULL);
1190 
1191   gdk_drawable_get_size (d, &width, &height);
1192   depth = gdk_drawable_get_depth (d);
1193 
1194   return static_printf ("%s:%p:%dx%dx%d",
1195 			G_OBJECT_TYPE_NAME (d),
1196 			GDK_DRAWABLE_HANDLE (d),
1197 			width, height, depth);
1198 }
1199 
1200 #endif /* G_ENABLE_DEBUG */
1201