]> Pileus Git - ~andy/gtk/blob - modules/engines/ms-windows/msw_style.c
Fix build breakage and avoid a warning
[~andy/gtk] / modules / engines / ms-windows / msw_style.c
1 /* MS-Windows Engine (aka GTK-Wimp)
2  *
3  * Copyright (C) 2003, 2004 Raymond Penners <raymond@dotsphinx.com>
4  * Copyright (C) 2006 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
5  * Includes code adapted from redmond95 by Owen Taylor, and
6  * gtk-nativewin by Evan Martin
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /*
25  * Useful resources:
26  *
27  *  http://lxr.mozilla.org/seamonkey/source/widget/src/windows/nsNativeThemeWin.cpp
28  *  http://lxr.mozilla.org/seamonkey/source/widget/src/windows/nsLookAndFeel.cpp
29  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/functions/drawthemebackground.asp
30  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/pantdraw_4b3g.asp
31  */
32
33 /* Include first, else we get redefinition warnings about STRICT */
34 #include "pango/pangowin32.h"
35
36 #include "msw_style.h"
37 #include "xp_theme.h"
38
39 #include <windows.h>
40 #include <math.h>
41 #include <string.h>
42 #include <stdio.h>
43
44 #include "gtk/gtk.h"
45 #include "gtk/gtk.h"
46
47 #ifdef BUILDING_STANDALONE
48 #include "gdk/gdkwin32.h"
49 #else
50 #include "gdk/win32/gdkwin32.h"
51 #endif
52
53
54 /* Default values, not normally used
55  */
56 static const GtkRequisition default_option_indicator_size = { 9, 8 };
57 static const GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
58
59 static GtkStyleClass *parent_class;
60 static HBRUSH g_dither_brush = NULL;
61
62 static HPEN g_light_pen = NULL;
63 static HPEN g_dark_pen = NULL;
64
65 typedef enum
66 {
67   CHECK_AA,
68   CHECK_BASE,
69   CHECK_BLACK,
70   CHECK_DARK,
71   CHECK_LIGHT,
72   CHECK_MID,
73   CHECK_TEXT,
74   CHECK_INCONSISTENT,
75   RADIO_BASE,
76   RADIO_BLACK,
77   RADIO_DARK,
78   RADIO_LIGHT,
79   RADIO_MID,
80   RADIO_TEXT
81 } Part;
82
83 #define PART_SIZE 13
84
85 static const unsigned char check_aa_bits[] = {
86   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
87   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
88   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92   0x00, 0x00, 0x00, 0x00
93 };
94 static const unsigned char check_base_bits[] = {
95   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96   0xfc, 0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00,
97   0xfc, 0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00,
98   0xfc, 0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00,
99   0xfc, 0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00,
100   0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101   0x00, 0x00, 0x00, 0x00
102 };
103 static const unsigned char check_black_bits[] = {
104   0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00,
105   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
106   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
107   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
108   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
109   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
110   0x00, 0x00, 0x00, 0x00
111 };
112 static const unsigned char check_dark_bits[] = {
113   0xff, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
114   0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
115   0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
116   0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
117   0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
118   0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
119   0x01, 0x00, 0x00, 0x00
120 };
121 static const unsigned char check_light_bits[] = {
122   0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
123   0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
124   0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
125   0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
126   0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
127   0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
128   0xfe, 0x1f, 0x00, 0x00
129 };
130 static const unsigned char check_mid_bits[] = {
131   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132   0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
133   0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
134   0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
135   0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
136   0x00, 0x08, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
137   0x00, 0x00, 0x00, 0x00
138 };
139 static const unsigned char check_text_bits[] = {
140   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141   0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
142   0x00, 0x03, 0x00, 0x00, 0x88, 0x03, 0x00, 0x00,
143   0xd8, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00,
144   0x70, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
145   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146   0x00, 0x00, 0x00, 0x00
147 };
148 static const unsigned char check_inconsistent_bits[] = {
149   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152   0xf0, 0x03, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00,
153   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155   0x00, 0x00, 0x00, 0x00
156 };
157 static const unsigned char radio_base_bits[] = {
158   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159   0xf0, 0x01, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00,
160   0xfc, 0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00,
161   0xfc, 0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00,
162   0xfc, 0x07, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00,
163   0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164   0x00, 0x00, 0x00, 0x00
165 };
166 static const unsigned char radio_black_bits[] = {
167   0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00,
168   0x0c, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
169   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
170   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
171   0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
172   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173   0x00, 0x00, 0x00, 0x00
174 };
175 static const unsigned char radio_dark_bits[] = {
176   0xf0, 0x01, 0x00, 0x00, 0x0c, 0x06, 0x00, 0x00,
177   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
178   0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
179   0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
180   0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
181   0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182   0x00, 0x00, 0x00, 0x00
183 };
184 static const unsigned char radio_light_bits[] = {
185   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186   0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
187   0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
188   0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
189   0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
190   0x00, 0x08, 0x00, 0x00, 0x0c, 0x06, 0x00, 0x00,
191   0xf0, 0x01, 0x00, 0x00
192 };
193 static const unsigned char radio_mid_bits[] = {
194   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195   0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
196   0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
197   0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
198   0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
199   0x0c, 0x06, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00,
200   0x00, 0x00, 0x00, 0x00
201 };
202 static const unsigned char radio_text_bits[] = {
203   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205   0xe0, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00,
206   0xf0, 0x01, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00,
207   0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209   0x00, 0x00, 0x00, 0x00
210 };
211
212 static struct
213 {
214   const unsigned char *bits;
215   cairo_surface_t *bmap;
216 } parts[] = {
217   { check_aa_bits, NULL           },
218   { check_base_bits, NULL         },
219   { check_black_bits, NULL        },
220   { check_dark_bits, NULL         },
221   { check_light_bits, NULL        },
222   { check_mid_bits, NULL          },
223   { check_text_bits, NULL         },
224   { check_inconsistent_bits, NULL },
225   { radio_base_bits, NULL         },
226   { radio_black_bits, NULL        },
227   { radio_dark_bits, NULL         },
228   { radio_light_bits, NULL        },
229   { radio_mid_bits, NULL          },
230   { radio_text_bits, NULL         }
231 };
232
233 static void
234 _cairo_draw_line (cairo_t  *cr,
235                   GdkColor *color,
236                   gint      x1,
237                   gint      y1,
238                   gint      x2,
239                   gint      y2)
240 {
241   cairo_save (cr);
242
243   gdk_cairo_set_source_color (cr, color);
244   cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
245   cairo_set_line_width (cr, 1.0);
246
247   cairo_move_to (cr, x1 + 0.5, y1 + 0.5);
248   cairo_line_to (cr, x2 + 0.5, y2 + 0.5);
249   cairo_stroke (cr);
250
251   cairo_restore (cr);
252 }
253
254 static void
255 _cairo_draw_rectangle (cairo_t *cr,
256                        GdkColor *color,
257                        gboolean filled,
258                        gint x,
259                        gint y,
260                        gint width,
261                        gint height)
262 {
263   gdk_cairo_set_source_color (cr, color);
264
265   if (filled)
266     {
267       cairo_rectangle (cr, x, y, width, height);
268       cairo_fill (cr);
269     }
270   else
271     {
272       cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
273       cairo_stroke (cr);
274     }
275 }
276
277 static gboolean
278 get_system_font (XpThemeClass klazz, XpThemeFont type, LOGFONTW *out_lf)
279 {
280   if (xp_theme_get_system_font (klazz, type, out_lf))
281     {
282       return TRUE;
283     }
284   else
285     {
286       /* Use wide char versions here, as the theming functions only support
287        * wide chars versions of the structures. */
288       NONCLIENTMETRICSW ncm;
289
290       ncm.cbSize = sizeof (NONCLIENTMETRICSW);
291
292       if (SystemParametersInfoW (SPI_GETNONCLIENTMETRICS,
293                                 sizeof (NONCLIENTMETRICSW), &ncm, 0))
294         {
295           if (type == XP_THEME_FONT_CAPTION)
296             *out_lf = ncm.lfCaptionFont;
297           else if (type == XP_THEME_FONT_MENU)
298             *out_lf = ncm.lfMenuFont;
299           else if (type == XP_THEME_FONT_STATUS)
300             *out_lf = ncm.lfStatusFont;
301           else
302             *out_lf = ncm.lfMessageFont;
303
304           return TRUE;
305         }
306     }
307
308   return FALSE;
309 }
310
311 static char *
312 sys_font_to_pango_font (XpThemeClass klazz, XpThemeFont type, char *buf,
313                         size_t bufsiz)
314 {
315   LOGFONTW lf;
316
317   if (get_system_font (klazz, type, &lf))
318     {
319       PangoFontDescription *desc = NULL;
320       int pt_size;
321       const char *font;
322
323       desc = pango_win32_font_description_from_logfontw (&lf);
324       if (!desc)
325         return NULL;
326
327       font = pango_font_description_to_string (desc);
328       pt_size = pango_font_description_get_size (desc);
329
330       if (!(font && *font))
331         {
332           pango_font_description_free (desc);
333           return NULL;
334         }
335
336       if (pt_size == 0)
337         {
338           HDC hDC;
339           HWND hwnd;
340
341           hwnd = GetDesktopWindow ();
342           hDC = GetDC (hwnd);
343
344           if (hDC)
345             pt_size = -MulDiv (lf.lfHeight, 72, GetDeviceCaps (hDC, LOGPIXELSY));
346           else
347             pt_size = 10;
348
349           if (hDC)
350             ReleaseDC (hwnd, hDC);
351
352           g_snprintf (buf, bufsiz, "%s %d", font, pt_size);
353         }
354       else
355         {
356           g_snprintf (buf, bufsiz, "%s", font);
357         }
358
359       if (desc)
360         pango_font_description_free (desc);
361
362       return buf;
363     }
364
365   return NULL;
366 }
367
368 /* missing from ms's header files */
369 #ifndef SPI_GETMENUSHOWDELAY
370 #define SPI_GETMENUSHOWDELAY 106
371 #endif
372
373 /* I don't know the proper XP theme class for things like
374    HIGHLIGHTTEXT, so we'll just define it to be "BUTTON"
375    for now */
376 #define XP_THEME_CLASS_TEXT XP_THEME_CLASS_BUTTON
377
378 #define WIN95_VERSION   0x400
379 #define WIN2K_VERSION   0x500
380 #define WINXP_VERSION   0x501
381 #define WIN2K3_VERSION  0x502
382 #define VISTA_VERSION   0x600
383
384 static gint32
385 get_windows_version ()
386 {
387   static gint32 version = 0;
388   static gboolean have_version = FALSE;
389
390   if (!have_version)
391     {
392       OSVERSIONINFOEX osvi;
393       have_version = TRUE;
394
395       ZeroMemory (&osvi, sizeof (OSVERSIONINFOEX));
396       osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
397
398       GetVersionEx((OSVERSIONINFO*) &osvi);
399
400       version = (osvi.dwMajorVersion & 0xff) << 8 | (osvi.dwMinorVersion & 0xff);
401     }
402
403   return version;
404 }
405
406 static void
407 setup_menu_settings (GtkSettings *settings)
408 {
409   int menu_delay;
410   GObjectClass *klazz = G_OBJECT_GET_CLASS (G_OBJECT (settings));
411
412   if (get_windows_version () > WIN95_VERSION)
413     {
414       if (SystemParametersInfo (SPI_GETMENUSHOWDELAY, 0, &menu_delay, 0))
415         {
416           if (klazz)
417             {
418               if (g_object_class_find_property
419                   (klazz, "gtk-menu-bar-popup-delay"))
420                 {
421                   g_object_set (settings,
422                                 "gtk-menu-bar-popup-delay", 0, NULL);
423                 }
424               if (g_object_class_find_property
425                   (klazz, "gtk-menu-popup-delay"))
426                 {
427                   g_object_set (settings,
428                                 "gtk-menu-popup-delay", menu_delay, NULL);
429                 }
430               if (g_object_class_find_property
431                   (klazz, "gtk-menu-popdown-delay"))
432                 {
433                   g_object_set (settings,
434                                 "gtk-menu-popdown-delay", menu_delay, NULL);
435                 }
436             }
437         }
438     }
439 }
440
441 void
442 msw_style_setup_system_settings (void)
443 {
444   GtkSettings *settings;
445   int cursor_blink_time;
446
447   settings = gtk_settings_get_default ();
448   if (!settings)
449     return;
450
451   cursor_blink_time = GetCaretBlinkTime ();
452   g_object_set (settings, "gtk-cursor-blink", cursor_blink_time > 0, NULL);
453
454   if (cursor_blink_time > 0)
455     {
456       g_object_set (settings, "gtk-cursor-blink-time",
457                     2 * cursor_blink_time, NULL);
458     }
459
460   g_object_set (settings, "gtk-double-click-distance",
461                 GetSystemMetrics (SM_CXDOUBLECLK), NULL);
462   g_object_set (settings, "gtk-double-click-time", GetDoubleClickTime (),
463                 NULL);
464   g_object_set (settings, "gtk-dnd-drag-threshold",
465                 GetSystemMetrics (SM_CXDRAG), NULL);
466
467   setup_menu_settings (settings);
468
469   /*
470      http://developer.gnome.org/doc/API/2.0/gtk/GtkSettings.html
471      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/systemparametersinfo.asp
472      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getsystemmetrics.asp */
473 }
474
475 static void
476 setup_system_font (GtkStyle *style)
477 {
478   char buf[256], *font;         /* It's okay, lfFaceName is smaller than 32
479                                    chars */
480
481   if ((font = sys_font_to_pango_font (XP_THEME_CLASS_TEXT,
482                                       XP_THEME_FONT_MESSAGE,
483                                       buf, sizeof (buf))) != NULL)
484     {
485       if (style->font_desc)
486         {
487           pango_font_description_free (style->font_desc);
488         }
489
490       style->font_desc = pango_font_description_from_string (font);
491     }
492 }
493
494 static void
495 sys_color_to_gtk_color (XpThemeClass klazz, int id, GdkColor * pcolor)
496 {
497   DWORD color;
498
499   if (!xp_theme_get_system_color (klazz, id, &color))
500     color = GetSysColor (id);
501
502   pcolor->pixel = color;
503   pcolor->red = (GetRValue (color) << 8) | GetRValue (color);
504   pcolor->green = (GetGValue (color) << 8) | GetGValue (color);
505   pcolor->blue = (GetBValue (color) << 8) | GetBValue (color);
506 }
507
508 static int
509 get_system_metric (XpThemeClass klazz, int id)
510 {
511   int rval;
512
513   if (!xp_theme_get_system_metric (klazz, id, &rval))
514     rval = GetSystemMetrics (id);
515
516   return rval;
517 }
518
519 static void
520 setup_msw_rc_style (void)
521 {
522   char buf[1024], font_buf[256], *font_ptr;
523   char menu_bar_prelight_str[128];
524
525   GdkColor menu_color;
526   GdkColor menu_text_color;
527   GdkColor tooltip_back;
528   GdkColor tooltip_fore;
529   GdkColor btn_fore;
530   GdkColor btn_face;
531   GdkColor progress_back;
532
533   GdkColor fg_prelight;
534   GdkColor bg_prelight;
535   GdkColor base_prelight;
536   GdkColor text_prelight;
537
538   /* Prelight */
539   sys_color_to_gtk_color (get_windows_version () >= VISTA_VERSION ? XP_THEME_CLASS_MENU : XP_THEME_CLASS_TEXT,
540                           get_windows_version () >= VISTA_VERSION ? COLOR_MENUTEXT : COLOR_HIGHLIGHTTEXT,
541                           &fg_prelight);
542   sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &bg_prelight);
543   sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
544                           &base_prelight);
545   sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
546                           &text_prelight);
547
548   sys_color_to_gtk_color (XP_THEME_CLASS_MENU, COLOR_MENUTEXT,
549                           &menu_text_color);
550   sys_color_to_gtk_color (XP_THEME_CLASS_MENU, COLOR_MENU, &menu_color);
551
552   /* tooltips */
553   sys_color_to_gtk_color (XP_THEME_CLASS_TOOLTIP, COLOR_INFOTEXT,
554                           &tooltip_fore);
555   sys_color_to_gtk_color (XP_THEME_CLASS_TOOLTIP, COLOR_INFOBK,
556                           &tooltip_back);
557
558   /* text on push buttons. TODO: button shadows, backgrounds, and
559      highlights */
560   sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &btn_fore);
561   sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &btn_face);
562
563   /* progress bar background color */
564   sys_color_to_gtk_color (XP_THEME_CLASS_PROGRESS, COLOR_HIGHLIGHT,
565                           &progress_back);
566
567   /* Enable coloring for menus. */
568   font_ptr =
569     sys_font_to_pango_font (XP_THEME_CLASS_MENU, XP_THEME_FONT_MENU,
570                             font_buf, sizeof (font_buf));
571   g_snprintf (buf, sizeof (buf),
572               "style \"msw-menu\" = \"msw-default\"\n" "{\n"
573               "GtkMenuItem::toggle-spacing = 8\n"
574               "fg[PRELIGHT] = { %d, %d, %d }\n"
575               "bg[PRELIGHT] = { %d, %d, %d }\n"
576               "text[PRELIGHT] = { %d, %d, %d }\n"
577               "base[PRELIGHT] = { %d, %d, %d }\n"
578               "fg[NORMAL] = { %d, %d, %d }\n"
579               "bg[NORMAL] = { %d, %d, %d }\n" "%s = \"%s\"\n"
580               "}widget_class \"*MenuItem*\" style \"msw-menu\"\n"
581               "widget_class \"*GtkMenu\" style \"msw-menu\"\n"
582               "widget_class \"*GtkMenuShell*\" style \"msw-menu\"\n",
583               fg_prelight.red, fg_prelight.green, fg_prelight.blue,
584               bg_prelight.red, bg_prelight.green, bg_prelight.blue,
585               text_prelight.red, text_prelight.green, text_prelight.blue,
586               base_prelight.red, base_prelight.green, base_prelight.blue,
587               menu_text_color.red, menu_text_color.green,
588               menu_text_color.blue, menu_color.red, menu_color.green,
589               menu_color.blue, (font_ptr ? "font_name" : "#"),
590               (font_ptr ? font_ptr : " font name should go here"));
591   gtk_rc_parse_string (buf);
592
593   if (xp_theme_is_active ())
594     {
595       *menu_bar_prelight_str = '\0';
596     }
597   else
598     {
599       g_snprintf (menu_bar_prelight_str, sizeof (menu_bar_prelight_str),
600                   "fg[PRELIGHT] = { %d, %d, %d }\n",
601                   menu_text_color.red, menu_text_color.green,
602                   menu_text_color.blue);
603     }
604
605   /* Enable coloring for menu bars. */
606   g_snprintf (buf, sizeof (buf),
607               "style \"msw-menu-bar\" = \"msw-menu\"\n"
608               "{\n"
609               "bg[NORMAL] = { %d, %d, %d }\n"
610               "%s" "GtkMenuBar::shadow-type = %d\n"
611               /*
612                  FIXME: This should be enabled once gtk+ support
613                  GtkMenuBar::prelight-item style property.
614                */
615               /* "GtkMenuBar::prelight-item = 1\n" */
616               "}widget_class \"*MenuBar*\" style \"msw-menu-bar\"\n",
617               btn_face.red, btn_face.green, btn_face.blue,
618               menu_bar_prelight_str, xp_theme_is_active ()? 0 : 2);
619   gtk_rc_parse_string (buf);
620
621   g_snprintf (buf, sizeof (buf),
622               "style \"msw-toolbar\" = \"msw-default\"\n"
623               "{\n"
624               "GtkHandleBox::shadow-type = %s\n"
625               "GtkToolbar::shadow-type = %s\n"
626               "}widget_class \"*HandleBox*\" style \"msw-toolbar\"\n",
627               "etched-in", "etched-in");
628   gtk_rc_parse_string (buf);
629
630   /* enable tooltip fonts */
631   font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,
632                                      font_buf, sizeof (font_buf));
633   g_snprintf (buf, sizeof (buf),
634               "style \"msw-tooltips-caption\" = \"msw-default\"\n"
635               "{fg[NORMAL] = { %d, %d, %d }\n" "%s = \"%s\"\n"
636               "}widget \"gtk-tooltips.GtkLabel\" style \"msw-tooltips-caption\"\n"
637               "widget \"gtk-tooltip.GtkLabel\" style \"msw-tooltips-caption\"\n",
638               tooltip_fore.red, tooltip_fore.green, tooltip_fore.blue,
639               (font_ptr ? "font_name" : "#"),
640               (font_ptr ? font_ptr : " font name should go here"));
641   gtk_rc_parse_string (buf);
642
643   g_snprintf (buf, sizeof (buf),
644               "style \"msw-tooltips\" = \"msw-default\"\n"
645               "{bg[NORMAL] = { %d, %d, %d }\n"
646               "}widget \"gtk-tooltips*\" style \"msw-tooltips\"\n"
647               "widget \"gtk-tooltip*\" style \"msw-tooltips\"\n",
648               tooltip_back.red, tooltip_back.green, tooltip_back.blue);
649   gtk_rc_parse_string (buf);
650
651   /* enable font theming for status bars */
652   font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,
653                                      font_buf, sizeof (font_buf));
654   g_snprintf (buf, sizeof (buf),
655               "style \"msw-status\" = \"msw-default\"\n" "{%s = \"%s\"\n"
656               "bg[NORMAL] = { %d, %d, %d }\n"
657               "}widget_class \"*Status*\" style \"msw-status\"\n",
658               (font_ptr ? "font_name" : "#"),
659               (font_ptr ? font_ptr : " font name should go here"),
660               btn_face.red, btn_face.green, btn_face.blue);
661   gtk_rc_parse_string (buf);
662
663   /* enable coloring for text on buttons TODO: use GetThemeMetric for the
664      border and outside border */
665   g_snprintf (buf, sizeof (buf),
666               "style \"msw-button\" = \"msw-default\"\n"
667               "{\n"
668               "bg[NORMAL] = { %d, %d, %d }\n"
669               "bg[PRELIGHT] = { %d, %d, %d }\n"
670               "bg[INSENSITIVE] = { %d, %d, %d }\n"
671               "fg[PRELIGHT] = { %d, %d, %d }\n"
672               "GtkButton::default-border = { 0, 0, 0, 0 }\n"
673               "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
674               "GtkButton::child-displacement-x = 1\n"
675               "GtkButton::child-displacement-y = 1\n"
676               "GtkButton::focus-padding = %d\n"
677               "}widget_class \"*Button*\" style \"msw-button\"\n",
678               btn_face.red, btn_face.green, btn_face.blue,
679               btn_face.red, btn_face.green, btn_face.blue,
680               btn_face.red, btn_face.green, btn_face.blue,
681               btn_fore.red, btn_fore.green, btn_fore.blue,
682               xp_theme_is_active ()? 1 : 2);
683   gtk_rc_parse_string (buf);
684
685   /* enable coloring for progress bars */
686   g_snprintf (buf, sizeof (buf),
687               "style \"msw-progress\" = \"msw-default\"\n"
688               "{bg[PRELIGHT] = { %d, %d, %d }\n"
689               "bg[NORMAL] = { %d, %d, %d }\n"
690               "}widget_class \"*Progress*\" style \"msw-progress\"\n",
691               progress_back.red,
692               progress_back.green,
693               progress_back.blue,
694               btn_face.red, btn_face.green, btn_face.blue);
695   gtk_rc_parse_string (buf);
696
697   /* scrollbar thumb width and height */
698   g_snprintf (buf, sizeof (buf),
699               "style \"msw-vscrollbar\" = \"msw-default\"\n"
700               "{GtkRange::slider-width = %d\n"
701               "GtkRange::stepper-size = %d\n"
702               "GtkRange::stepper-spacing = 0\n"
703               "GtkRange::trough_border = 0\n"
704               "GtkScale::slider-length = %d\n"
705               "GtkScrollbar::min-slider-length = 8\n"
706               "}widget_class \"*VScrollbar*\" style \"msw-vscrollbar\"\n"
707               "widget_class \"*VScale*\" style \"msw-vscrollbar\"\n",
708               GetSystemMetrics (SM_CYVTHUMB),
709               get_system_metric (XP_THEME_CLASS_SCROLLBAR, SM_CXVSCROLL), 11);
710   gtk_rc_parse_string (buf);
711
712   g_snprintf (buf, sizeof (buf),
713               "style \"msw-hscrollbar\" = \"msw-default\"\n"
714               "{GtkRange::slider-width = %d\n"
715               "GtkRange::stepper-size = %d\n"
716               "GtkRange::stepper-spacing = 0\n"
717               "GtkRange::trough_border = 0\n"
718               "GtkScale::slider-length = %d\n"
719               "GtkScrollbar::min-slider-length = 8\n"
720               "}widget_class \"*HScrollbar*\" style \"msw-hscrollbar\"\n"
721               "widget_class \"*HScale*\" style \"msw-hscrollbar\"\n",
722               GetSystemMetrics (SM_CXHTHUMB),
723               get_system_metric (XP_THEME_CLASS_SCROLLBAR, SM_CYHSCROLL), 11);
724   gtk_rc_parse_string (buf);
725
726   gtk_rc_parse_string ("style \"msw-scrolled-window\" = \"msw-default\"\n"
727                        "{GtkScrolledWindow::scrollbars-within-bevel = 1}\n"
728                        "class \"GtkScrolledWindow\" style \"msw-scrolled-window\"\n");
729
730   /* radio/check button sizes */
731   g_snprintf (buf, sizeof (buf),
732               "style \"msw-checkbutton\" = \"msw-button\"\n"
733               "{GtkCheckButton::indicator-size = 13\n"
734               "}widget_class \"*CheckButton*\" style \"msw-checkbutton\"\n"
735               "widget_class \"*RadioButton*\" style \"msw-checkbutton\"\n");
736   gtk_rc_parse_string (buf);
737
738   /* size of combo box toggle button */
739   g_snprintf (buf, sizeof (buf),
740               "style \"msw-combobox-button\" = \"msw-default\"\n"
741               "{\n"
742               "xthickness = 0\n"
743               "ythickness = 0\n"
744               "GtkButton::default-border = { 0, 0, 0, 0 }\n"
745               "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
746               "GtkButton::child-displacement-x = 0\n"
747               "GtkButton::child-displacement-y = 0\n"
748               "GtkWidget::focus-padding = 0\n"
749               "GtkWidget::focus-line-width = 0\n"
750               "}\n"
751               "widget_class \"*ComboBox*ToggleButton*\" style \"msw-combobox-button\"\n");
752   gtk_rc_parse_string (buf);
753
754   g_snprintf (buf, sizeof (buf),
755               "style \"msw-combobox\" = \"msw-default\"\n"
756               "{\n"
757               "GtkComboBox::shadow-type = in\n"
758               "xthickness = %d\n"
759               "ythickness = %d\n"
760               "}\n"
761               "class \"GtkComboBox\" style \"msw-combobox\"\n",
762         xp_theme_is_active()? 1 : GetSystemMetrics (SM_CXEDGE),
763         xp_theme_is_active()? 1 : GetSystemMetrics (SM_CYEDGE));
764   gtk_rc_parse_string (buf);
765
766   /* size of tree view header */
767   g_snprintf (buf, sizeof (buf),
768               "style \"msw-header-button\" = \"msw-default\"\n"
769               "{\n"
770               "xthickness = 0\n"
771               "ythickness = 0\n"
772               "GtkWidget::draw-border = {0, 0, 0, 0}\n"
773         "GtkButton::default-border = { 0, 0, 0, 0 }\n"
774               "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
775               "GtkButton::child-displacement-x = 0\n"
776               "GtkButton::child-displacement-y = 0\n"
777               "GtkWidget::focus-padding = 0\n"
778               "GtkWidget::focus-line-width = 0\n"
779               "}\n"
780               "widget_class \"*TreeView*Button*\" style \"msw-header-button\"\n");
781   gtk_rc_parse_string (buf);
782
783   /* FIXME: This should be enabled once gtk+ support GtkNotebok::prelight-tab */
784   /* enable prelight tab of GtkNotebook */
785   /*
786      g_snprintf (buf, sizeof (buf),
787      "style \"msw-notebook\" = \"msw-default\"\n"
788      "{GtkNotebook::prelight-tab=1\n"
789      "}widget_class \"*Notebook*\" style \"msw-notebook\"\n");
790      gtk_rc_parse_string (buf);
791    */
792
793   /* FIXME: This should be enabled once gtk+ support GtkTreeView::full-row-focus */
794   /*
795      g_snprintf (buf, sizeof (buf),
796      "style \"msw-treeview\" = \"msw-default\"\n"
797      "{GtkTreeView::full-row-focus=0\n"
798      "}widget_class \"*TreeView*\" style \"msw-treeview\"\n");
799      gtk_rc_parse_string (buf);
800    */
801 }
802
803 static void
804 setup_system_styles (GtkStyle *style)
805 {
806   int i;
807
808   /* Default background */
809   sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
810                           &style->bg[GTK_STATE_NORMAL]);
811   sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
812                           &style->bg[GTK_STATE_SELECTED]);
813   sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
814                           &style->bg[GTK_STATE_INSENSITIVE]);
815   sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
816                           &style->bg[GTK_STATE_ACTIVE]);
817   sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
818                           &style->bg[GTK_STATE_PRELIGHT]);
819
820   /* Default base */
821   sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOW,
822                           &style->base[GTK_STATE_NORMAL]);
823   sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT,
824                           &style->base[GTK_STATE_SELECTED]);
825   sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
826                           &style->base[GTK_STATE_INSENSITIVE]);
827   sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNFACE,
828                           &style->base[GTK_STATE_ACTIVE]);
829   sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOW,
830                           &style->base[GTK_STATE_PRELIGHT]);
831
832   /* Default text */
833   sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
834                           &style->text[GTK_STATE_NORMAL]);
835   sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
836                           &style->text[GTK_STATE_SELECTED]);
837   sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_GRAYTEXT,
838                           &style->text[GTK_STATE_INSENSITIVE]);
839   sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
840                           &style->text[GTK_STATE_ACTIVE]);
841   sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
842                           &style->text[GTK_STATE_PRELIGHT]);
843
844   /* Default foreground */
845   sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
846                           &style->fg[GTK_STATE_NORMAL]);
847   sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT,
848                           &style->fg[GTK_STATE_SELECTED]);
849   sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_GRAYTEXT,
850                           &style->fg[GTK_STATE_INSENSITIVE]);
851   sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT,
852                           &style->bg[GTK_STATE_ACTIVE]);
853   sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT,
854                           &style->fg[GTK_STATE_PRELIGHT]);
855
856   for (i = 0; i < 5; i++)
857     {
858       sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_3DSHADOW,
859                               &style->dark[i]);
860       sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_3DHILIGHT,
861                               &style->light[i]);
862
863       style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
864       style->mid[i].green =
865         (style->light[i].green + style->dark[i].green) / 2;
866       style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
867
868       style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
869       style->text_aa[i].green =
870         (style->text[i].green + style->base[i].green) / 2;
871       style->text_aa[i].blue =
872         (style->text[i].blue + style->base[i].blue) / 2;
873     }
874 }
875
876 static XpThemeElement
877 map_gtk_progress_bar_to_xp (GtkProgressBar *progress_bar, gboolean trough)
878 {
879   XpThemeElement ret;
880
881   switch (gtk_orientable_get_orientation (GTK_ORIENTABLE (progress_bar)))
882     {
883     case GTK_ORIENTATION_HORIZONTAL:
884       ret = trough
885         ? XP_THEME_ELEMENT_PROGRESS_TROUGH_H
886         : XP_THEME_ELEMENT_PROGRESS_BAR_H;
887       break;
888
889     default:
890       ret = trough
891         ? XP_THEME_ELEMENT_PROGRESS_TROUGH_V
892         : XP_THEME_ELEMENT_PROGRESS_BAR_V;
893       break;
894     }
895
896   return ret;
897 }
898
899 static gboolean
900 is_combo_box_child (GtkWidget *w)
901 {
902   GtkWidget *tmp;
903
904   if (w == NULL)
905     return FALSE;
906
907   for (tmp = gtk_widget_get_parent (w); tmp; tmp = gtk_widget_get_parent (tmp))
908     {
909       if (GTK_IS_COMBO_BOX (tmp))
910         return TRUE;
911     }
912
913   return FALSE;
914 }
915
916 /* This function is not needed anymore */
917 /* static gboolean
918 combo_box_draw_arrow (GtkStyle *style,
919                       cairo_t *cr,
920                       GtkStateType state,
921                       GtkWidget *widget)
922 {
923   if (xp_theme_is_active ())
924     return TRUE;
925
926   if (widget && GTK_IS_TOGGLE_BUTTON (widget->parent))
927     {
928       DWORD border;
929       RECT rect;
930       HDC dc;
931       XpDCInfo dc_info;
932
933       dc = get_window_dc (style, cr, state, &dc_info, area->x, area->y, area->width,
934                           area->height, &rect);
935       border = (GTK_TOGGLE_BUTTON (gtk_widget_get_parent (widget))->
936                 active ? DFCS_PUSHED | DFCS_FLAT : 0);
937
938       InflateRect (&rect, 1, 1);
939       DrawFrameControl (dc, &rect, DFC_SCROLL, DFCS_SCROLLDOWN | border);
940
941       release_window_dc (&dc_info);
942
943       return TRUE;
944     }
945
946   return FALSE;
947 }*/
948
949 static void
950 draw_part (cairo_t *cr,
951            GdkColor *gc, gint x, gint y, Part part)
952 {
953   if (!parts[part].bmap)
954     {
955       parts[part].bmap = cairo_image_surface_create_for_data ((unsigned char *)parts[part].bits,
956                                                               CAIRO_FORMAT_A1,
957                                                               PART_SIZE, PART_SIZE, 4);
958     }
959
960   gdk_cairo_set_source_color (cr, gc);
961   cairo_mask_surface (cr, parts[part].bmap, x, y);
962 }
963
964 static void
965 draw_check (GtkStyle *style,
966             cairo_t *cr,
967             GtkStateType state,
968             GtkShadowType shadow,
969             GtkWidget *widget,
970             const gchar *detail, gint x, gint y, gint width, gint height)
971 {
972   x -= (1 + PART_SIZE - width) / 2;
973   y -= (1 + PART_SIZE - height) / 2;
974
975   if (detail && strcmp (detail, "check") == 0)  /* Menu item */
976     {
977       if (shadow == GTK_SHADOW_IN)
978         {
979           draw_part (cr, &style->black, x, y, CHECK_TEXT);
980           draw_part (cr, &style->dark[state], x, y, CHECK_AA);
981         }
982     }
983   else
984     {
985       XpThemeElement theme_elt = XP_THEME_ELEMENT_CHECKBOX;
986       switch (shadow)
987         {
988         case GTK_SHADOW_ETCHED_IN:
989           theme_elt = XP_THEME_ELEMENT_INCONSISTENT_CHECKBOX;
990           break;
991
992         case GTK_SHADOW_IN:
993           theme_elt = XP_THEME_ELEMENT_PRESSED_CHECKBOX;
994           break;
995
996         default:
997           break;
998         }
999
1000       if (!xp_theme_draw (cr, theme_elt,
1001                           style, x, y, width, height, state))
1002         {
1003           if (detail && !strcmp (detail, "cellcheck"))
1004             state = GTK_STATE_NORMAL;
1005
1006           draw_part (cr, &style->black, x, y, CHECK_BLACK);
1007           draw_part (cr, &style->dark[state], x, y, CHECK_DARK);
1008           draw_part (cr, &style->mid[state], x, y, CHECK_MID);
1009           draw_part (cr, &style->light[state], x, y, CHECK_LIGHT);
1010           draw_part (cr, &style->base[state], x, y, CHECK_BASE);
1011
1012           if (shadow == GTK_SHADOW_IN)
1013             {
1014               draw_part (cr, &style->text[state], x, y, CHECK_TEXT);
1015               draw_part (cr, &style->text_aa[state], x, y, CHECK_AA);
1016             }
1017           else if (shadow == GTK_SHADOW_ETCHED_IN)
1018             {
1019               draw_part (cr, &style->text[state], x, y, CHECK_INCONSISTENT);
1020               draw_part (cr, &style->text_aa[state], x, y, CHECK_AA);
1021             }
1022         }
1023     }
1024 }
1025
1026 static void
1027 draw_expander (GtkStyle *style,
1028                cairo_t *cr,
1029                GtkStateType state,
1030                GtkWidget *widget,
1031                const gchar *detail,
1032                gint x, gint y, GtkExpanderStyle expander_style)
1033 {
1034   gint expander_size;
1035   gint expander_semi_size;
1036   XpThemeElement xp_expander;
1037
1038   gtk_widget_style_get (widget, "expander_size", &expander_size, NULL);
1039
1040   switch (expander_style)
1041     {
1042     case GTK_EXPANDER_COLLAPSED:
1043     case GTK_EXPANDER_SEMI_COLLAPSED:
1044       xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED;
1045       break;
1046
1047     default:
1048       xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED;
1049       break;
1050     }
1051
1052   if ((expander_size % 2) == 0)
1053     expander_size--;
1054
1055   if (expander_size > 2)
1056     expander_size -= 2;
1057
1058 /* FIXME: wtf?
1059       gdk_cairo_set_source_color (cr, &style->fg[state]);
1060  */
1061
1062   expander_semi_size = expander_size / 2;
1063   x -= expander_semi_size;
1064   y -= expander_semi_size;
1065
1066   if (!xp_theme_draw (cr, xp_expander, style,
1067                       x, y, expander_size, expander_size, state))
1068     {
1069       HDC dc;
1070       RECT rect;
1071       HPEN pen;
1072       HGDIOBJ old_pen;
1073       XpDCInfo dc_info;
1074
1075       dc = get_window_dc (style, cr, state, &dc_info, x, y, expander_size,
1076                           expander_size, &rect);
1077       FrameRect (dc, &rect, GetSysColorBrush (COLOR_GRAYTEXT));
1078       InflateRect (&rect, -1, -1);
1079       FillRect (dc, &rect,
1080                 GetSysColorBrush (state ==
1081                                   GTK_STATE_INSENSITIVE ? COLOR_BTNFACE :
1082                                   COLOR_WINDOW));
1083
1084       InflateRect (&rect, -1, -1);
1085
1086       pen = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_WINDOWTEXT));
1087       old_pen = SelectObject (dc, pen);
1088
1089       MoveToEx (dc, rect.left, rect.top - 2 + expander_semi_size, NULL);
1090       LineTo (dc, rect.right, rect.top - 2 + expander_semi_size);
1091
1092       if (expander_style == GTK_EXPANDER_COLLAPSED ||
1093           expander_style == GTK_EXPANDER_SEMI_COLLAPSED)
1094         {
1095           MoveToEx (dc, rect.left - 2 + expander_semi_size, rect.top, NULL);
1096           LineTo (dc, rect.left - 2 + expander_semi_size, rect.bottom);
1097         }
1098
1099       SelectObject (dc, old_pen);
1100       DeleteObject (pen);
1101       release_window_dc (&dc_info);
1102     }
1103 }
1104
1105 static void
1106 draw_option (GtkStyle *style,
1107              cairo_t *cr,
1108              GtkStateType state,
1109              GtkShadowType shadow,
1110              GtkWidget *widget,
1111              const gchar *detail, gint x, gint y, gint width, gint height)
1112 {
1113   x -= (1 + PART_SIZE - width) / 2;
1114   y -= (1 + PART_SIZE - height) / 2;
1115
1116   if (detail && strcmp (detail, "option") == 0) /* Menu item */
1117     {
1118       if (shadow == GTK_SHADOW_IN)
1119         {
1120           draw_part (cr, &style->fg[state], x, y, RADIO_TEXT);
1121         }
1122     }
1123   else
1124     {
1125       if (xp_theme_draw (cr, shadow == GTK_SHADOW_IN
1126                          ? XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON
1127                          : XP_THEME_ELEMENT_RADIO_BUTTON,
1128                          style, x, y, width, height, state))
1129         {
1130         }
1131       else
1132         {
1133           if (detail && !strcmp (detail, "cellradio"))
1134             state = GTK_STATE_NORMAL;
1135
1136           draw_part (cr, &style->black, x, y, RADIO_BLACK);
1137           draw_part (cr, &style->dark[state], x, y, RADIO_DARK);
1138           draw_part (cr, &style->mid[state], x, y, RADIO_MID);
1139           draw_part (cr, &style->light[state], x, y, RADIO_LIGHT);
1140           draw_part (cr, &style->base[state], x, y, RADIO_BASE);
1141
1142           if (shadow == GTK_SHADOW_IN)
1143             draw_part (cr, &style->text[state], x, y, RADIO_TEXT);
1144         }
1145     }
1146 }
1147
1148 static void
1149 draw_varrow (cairo_t *cr,
1150              GdkColor *gc,
1151              GtkShadowType shadow_type,
1152              GtkArrowType arrow_type, gint x, gint y, gint width, gint height)
1153 {
1154   gint steps, extra;
1155   gint y_start, y_increment;
1156   gint i;
1157
1158   width = width + width % 2 - 1;        /* Force odd */
1159   steps = 1 + width / 2;
1160   extra = height - steps;
1161
1162   if (arrow_type == GTK_ARROW_DOWN)
1163     {
1164       y_start = y;
1165       y_increment = 1;
1166     }
1167   else
1168     {
1169       y_start = y + height - 1;
1170       y_increment = -1;
1171     }
1172
1173   for (i = extra; i < height; i++)
1174     {
1175       _cairo_draw_line (cr, gc,
1176                      x + (i - extra), y_start + i * y_increment,
1177                      x + width - (i - extra) - 1, y_start + i * y_increment);
1178     }
1179 }
1180
1181 static void
1182 draw_harrow (cairo_t *cr,
1183              GdkColor *gc,
1184              GtkShadowType shadow_type,
1185              GtkArrowType arrow_type, gint x, gint y, gint width, gint height)
1186 {
1187   gint steps, extra;
1188   gint x_start, x_increment;
1189   gint i;
1190
1191   height = height + height % 2 - 1;     /* Force odd */
1192   steps = 1 + height / 2;
1193   extra = width - steps;
1194
1195   if (arrow_type == GTK_ARROW_RIGHT)
1196     {
1197       x_start = x;
1198       x_increment = 1;
1199     }
1200   else
1201     {
1202       x_start = x + width - 1;
1203       x_increment = -1;
1204     }
1205
1206   for (i = extra; i < width; i++)
1207     {
1208       _cairo_draw_line (cr, gc,
1209                      x_start + i * x_increment, y + (i - extra),
1210                      x_start + i * x_increment, y + height - (i - extra) - 1);
1211     }
1212 }
1213
1214 /* This function makes up for some brokeness in gtkrange.c
1215  * where we never get the full arrow of the stepper button
1216  * and the type of button in a single drawing function.
1217  *
1218  * It doesn't work correctly when the scrollbar is squished
1219  * to the point we don't have room for full-sized steppers.
1220  */
1221 static void
1222 reverse_engineer_stepper_box (GtkWidget *range,
1223                               GtkArrowType arrow_type,
1224                               gint *x, gint *y, gint *width, gint *height)
1225 {
1226   gint slider_width = 14, stepper_size = 14;
1227   gint box_width;
1228   gint box_height;
1229
1230   if (range)
1231     {
1232       gtk_widget_style_get (range,
1233                             "slider_width", &slider_width,
1234                             "stepper_size", &stepper_size, NULL);
1235     }
1236
1237   if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1238     {
1239       box_width = slider_width;
1240       box_height = stepper_size;
1241     }
1242   else
1243     {
1244       box_width = stepper_size;
1245       box_height = slider_width;
1246     }
1247
1248   *x = *x - (box_width - *width) / 2;
1249   *y = *y - (box_height - *height) / 2;
1250   *width = box_width;
1251   *height = box_height;
1252 }
1253
1254 static XpThemeElement
1255 to_xp_arrow (GtkArrowType arrow_type)
1256 {
1257   XpThemeElement xp_arrow;
1258
1259   switch (arrow_type)
1260     {
1261     case GTK_ARROW_UP:
1262       xp_arrow = XP_THEME_ELEMENT_ARROW_UP;
1263       break;
1264
1265     case GTK_ARROW_DOWN:
1266       xp_arrow = XP_THEME_ELEMENT_ARROW_DOWN;
1267       break;
1268
1269     case GTK_ARROW_LEFT:
1270       xp_arrow = XP_THEME_ELEMENT_ARROW_LEFT;
1271       break;
1272
1273     default:
1274       xp_arrow = XP_THEME_ELEMENT_ARROW_RIGHT;
1275       break;
1276     }
1277
1278   return xp_arrow;
1279 }
1280
1281 static void
1282 draw_arrow (GtkStyle *style,
1283             cairo_t *cr,
1284             GtkStateType state,
1285             GtkShadowType shadow,
1286             GtkWidget *widget,
1287             const gchar *detail,
1288             GtkArrowType arrow_type,
1289             gboolean fill, gint x, gint y, gint width, gint height)
1290 {
1291   const gchar *name;
1292   HDC dc;
1293   RECT rect;
1294   XpDCInfo dc_info;
1295
1296   name = gtk_widget_get_name (widget);
1297
1298   if (GTK_IS_ARROW (widget) && is_combo_box_child (widget) && xp_theme_is_active ())
1299     return;
1300
1301   if (detail && strcmp (detail, "spinbutton") == 0)
1302     {
1303       if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1304         {
1305           return;
1306         }
1307
1308       width -= 2;
1309       --height;
1310       if (arrow_type == GTK_ARROW_DOWN)
1311         ++y;
1312       ++x;
1313
1314       if (state == GTK_STATE_ACTIVE)
1315         {
1316           ++x;
1317           ++y;
1318         }
1319
1320       draw_varrow (cr, &style->fg[state], shadow,
1321                    arrow_type, x, y, width, height);
1322
1323       return;
1324     }
1325   else if (detail && (!strcmp (detail, "vscrollbar")
1326                       || !strcmp (detail, "hscrollbar")))
1327     {
1328       gboolean is_disabled = FALSE;
1329       UINT btn_type = 0;
1330       GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
1331
1332       gint box_x = x;
1333       gint box_y = y;
1334       gint box_width = width;
1335       gint box_height = height;
1336
1337       reverse_engineer_stepper_box (widget, arrow_type,
1338                                     &box_x, &box_y, &box_width, &box_height);
1339
1340       if (gtk_range_get_adjustment(&scrollbar->range)->page_size >=
1341           (gtk_range_get_adjustment(&scrollbar->range)->upper -
1342            gtk_range_get_adjustment(&scrollbar->range)->lower))
1343         {
1344           is_disabled = TRUE;
1345         }
1346
1347       if (xp_theme_draw (cr, to_xp_arrow (arrow_type), style, box_x, box_y,
1348                          box_width, box_height, state))
1349         {
1350         }
1351       else
1352         {
1353           switch (arrow_type)
1354             {
1355             case GTK_ARROW_UP:
1356               btn_type = DFCS_SCROLLUP;
1357               break;
1358
1359             case GTK_ARROW_DOWN:
1360               btn_type = DFCS_SCROLLDOWN;
1361               break;
1362
1363             case GTK_ARROW_LEFT:
1364               btn_type = DFCS_SCROLLLEFT;
1365               break;
1366
1367             case GTK_ARROW_RIGHT:
1368               btn_type = DFCS_SCROLLRIGHT;
1369               break;
1370
1371             case GTK_ARROW_NONE:
1372               break;
1373             }
1374
1375           if (state == GTK_STATE_INSENSITIVE)
1376             {
1377               btn_type |= DFCS_INACTIVE;
1378             }
1379
1380           if (widget)
1381             {
1382               dc = get_window_dc (style, cr, state, &dc_info,
1383                                   box_x, box_y, box_width, box_height, &rect);
1384               DrawFrameControl (dc, &rect, DFC_SCROLL,
1385                                 btn_type | (shadow ==
1386                                             GTK_SHADOW_IN ? (DFCS_PUSHED |
1387                                                              DFCS_FLAT) : 0));
1388               release_window_dc (&dc_info);
1389             }
1390         }
1391     }
1392   else
1393     {
1394       /* draw the toolbar chevrons - waiting for GTK 2.4 */
1395       if (name && !strcmp (name, "gtk-toolbar-arrow"))
1396         {
1397           if (xp_theme_draw
1398               (cr, XP_THEME_ELEMENT_REBAR_CHEVRON, style, x, y,
1399                width, height, state))
1400             {
1401               return;
1402             }
1403         }
1404       /* probably a gtk combo box on a toolbar */
1405       else if (0                /* gtk_widget_get_parent (widget) && GTK_IS_BUTTON
1406                                    (gtk_widget_get_parent (widget)) */ )
1407         {
1408           GtkAllocation allocation;
1409
1410           gtk_widget_get_allocation (widget, &allocation);
1411           if (xp_theme_draw
1412               (cr, XP_THEME_ELEMENT_COMBOBUTTON, style, x - 3,
1413                allocation.y + 1, width + 5,
1414                allocation.height - 4, state))
1415             {
1416               return;
1417             }
1418         }
1419
1420       if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1421         {
1422           x += (width - 7) / 2;
1423           y += (height - 5) / 2;
1424
1425           draw_varrow (cr, &style->fg[state], shadow,
1426                        arrow_type, x, y, 7, 5);
1427         }
1428       else
1429         {
1430           x += (width - 5) / 2;
1431           y += (height - 7) / 2;
1432
1433           draw_harrow (cr, &style->fg[state], shadow,
1434                        arrow_type, x, y, 5, 7);
1435         }
1436     }
1437 }
1438
1439 static void
1440 option_menu_get_props (GtkWidget *widget,
1441                        GtkRequisition *indicator_size,
1442                        GtkBorder *indicator_spacing)
1443 {
1444   GtkRequisition *tmp_size = NULL;
1445   GtkBorder *tmp_spacing = NULL;
1446
1447   if (widget)
1448     gtk_widget_style_get (widget,
1449                           "indicator_size", &tmp_size,
1450                           "indicator_spacing", &tmp_spacing, NULL);
1451
1452   if (tmp_size)
1453     {
1454       *indicator_size = *tmp_size;
1455       gtk_requisition_free (tmp_size);
1456     }
1457   else
1458     {
1459       *indicator_size = default_option_indicator_size;
1460     }
1461
1462   if (tmp_spacing)
1463     {
1464       *indicator_spacing = *tmp_spacing;
1465       gtk_border_free (tmp_spacing);
1466     }
1467   else
1468     {
1469       *indicator_spacing = default_option_indicator_spacing;
1470     }
1471 }
1472
1473 static gboolean
1474 is_toolbar_child (GtkWidget *wid)
1475 {
1476   while (wid)
1477     {
1478       if (GTK_IS_TOOLBAR (wid) || GTK_IS_HANDLE_BOX (wid))
1479         return TRUE;
1480       else
1481         wid = gtk_widget_get_parent (wid);
1482     }
1483
1484   return FALSE;
1485 }
1486
1487 static gboolean
1488 is_menu_tool_button_child (GtkWidget *wid)
1489 {
1490   while (wid)
1491     {
1492       if (GTK_IS_MENU_TOOL_BUTTON (wid))
1493         return TRUE;
1494       else
1495         wid = gtk_widget_get_parent (wid);
1496     }
1497   return FALSE;
1498 }
1499
1500 static HPEN
1501 get_light_pen ()
1502 {
1503   if (!g_light_pen)
1504     {
1505       g_light_pen = CreatePen (PS_SOLID | PS_INSIDEFRAME, 1,
1506                                GetSysColor (COLOR_BTNHIGHLIGHT));
1507     }
1508
1509   return g_light_pen;
1510 }
1511
1512 static HPEN
1513 get_dark_pen ()
1514 {
1515   if (!g_dark_pen)
1516     {
1517       g_dark_pen = CreatePen (PS_SOLID | PS_INSIDEFRAME, 1,
1518                               GetSysColor (COLOR_BTNSHADOW));
1519     }
1520
1521   return g_dark_pen;
1522 }
1523
1524 static void
1525 draw_3d_border (HDC hdc, RECT *rc, gboolean sunken)
1526 {
1527   HPEN pen1, pen2;
1528   HGDIOBJ old_pen;
1529
1530   if (sunken)
1531     {
1532       pen1 = get_dark_pen ();
1533       pen2 = get_light_pen ();
1534     }
1535   else
1536     {
1537       pen1 = get_light_pen ();
1538       pen2 = get_dark_pen ();
1539     }
1540
1541   MoveToEx (hdc, rc->left, rc->bottom - 1, NULL);
1542
1543   old_pen = SelectObject (hdc, pen1);
1544   LineTo (hdc, rc->left, rc->top);
1545   LineTo (hdc, rc->right - 1, rc->top);
1546   SelectObject (hdc, old_pen);
1547
1548   old_pen = SelectObject (hdc, pen2);
1549   LineTo (hdc, rc->right - 1, rc->bottom - 1);
1550   LineTo (hdc, rc->left, rc->bottom - 1);
1551   SelectObject (hdc, old_pen);
1552 }
1553
1554 static gboolean
1555 draw_menu_item (cairo_t *cr, GtkWidget *widget, GtkStyle *style,
1556                 gint x, gint y, gint width, gint height,
1557                 GtkStateType state_type)
1558 {
1559   GtkWidget *parent;
1560   GtkMenuShell *bar;
1561   HDC dc;
1562   RECT rect;
1563   XpDCInfo dc_info;
1564
1565   if (xp_theme_is_active ())
1566     {
1567       return (xp_theme_draw (cr, XP_THEME_ELEMENT_MENU_ITEM, style,
1568                              x, y, width, height, state_type));
1569     }
1570
1571   if ((parent = gtk_widget_get_parent (widget))
1572       && GTK_IS_MENU_BAR (parent) && !xp_theme_is_active ())
1573     {
1574       bar = GTK_MENU_SHELL (parent);
1575
1576       dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
1577
1578       if (state_type == GTK_STATE_PRELIGHT)
1579         {
1580           draw_3d_border (dc, &rect, bar->active);
1581         }
1582
1583       release_window_dc (&dc_info);
1584
1585       return TRUE;
1586     }
1587
1588   return FALSE;
1589 }
1590
1591 static HBRUSH
1592 get_dither_brush (void)
1593 {
1594   WORD pattern[8];
1595   HBITMAP pattern_bmp;
1596   int i;
1597
1598   if (g_dither_brush)
1599     return g_dither_brush;
1600
1601   for (i = 0; i < 8; i++)
1602     {
1603       pattern[i] = (WORD) (0x5555 << (i & 1));
1604     }
1605
1606   pattern_bmp = CreateBitmap (8, 8, 1, 1, &pattern);
1607
1608   if (pattern_bmp)
1609     {
1610       g_dither_brush = CreatePatternBrush (pattern_bmp);
1611       DeleteObject (pattern_bmp);
1612     }
1613
1614   return g_dither_brush;
1615 }
1616
1617 static gboolean
1618 draw_tool_button (cairo_t *cr, GtkWidget *widget, GtkStyle *style,
1619                   gint x, gint y, gint width, gint height,
1620                   GtkStateType state_type)
1621 {
1622   HDC dc;
1623   RECT rect;
1624   XpDCInfo dc_info;
1625   gboolean is_toggled = FALSE;
1626
1627   if (xp_theme_is_active ())
1628     {
1629       return (xp_theme_draw (cr, XP_THEME_ELEMENT_TOOLBAR_BUTTON, style,
1630                              x, y, width, height, state_type));
1631     }
1632
1633   if (GTK_IS_TOGGLE_BUTTON (widget))
1634     {
1635       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
1636         {
1637           is_toggled = TRUE;
1638         }
1639     }
1640
1641   if (state_type != GTK_STATE_PRELIGHT
1642       && state_type != GTK_STATE_ACTIVE && !is_toggled)
1643     {
1644       return FALSE;
1645     }
1646
1647   dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
1648   if (state_type == GTK_STATE_PRELIGHT)
1649     {
1650       if (is_toggled)
1651         {
1652           FillRect (dc, &rect, GetSysColorBrush (COLOR_BTNFACE));
1653         }
1654
1655       draw_3d_border (dc, &rect, is_toggled);
1656     }
1657   else if (state_type == GTK_STATE_ACTIVE)
1658     {
1659       if (is_toggled && !is_menu_tool_button_child (gtk_widget_get_parent (widget)))
1660         {
1661           SetTextColor (dc, GetSysColor (COLOR_3DHILIGHT));
1662           SetBkColor (dc, GetSysColor (COLOR_BTNFACE));
1663           FillRect (dc, &rect, get_dither_brush ());
1664         }
1665
1666       draw_3d_border (dc, &rect, TRUE);
1667     }
1668
1669   release_window_dc (&dc_info);
1670
1671   return TRUE;
1672 }
1673
1674 static void
1675 draw_push_button (cairo_t *cr, GtkWidget *widget, GtkStyle *style,
1676                   gint x, gint y, gint width, gint height,
1677                   GtkStateType state_type, gboolean is_default)
1678 {
1679   HDC dc;
1680   RECT rect;
1681   XpDCInfo dc_info;
1682
1683   dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
1684
1685   if (GTK_IS_TOGGLE_BUTTON (widget))
1686     {
1687       if (state_type == GTK_STATE_PRELIGHT &&
1688           gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
1689         {
1690           state_type = GTK_STATE_ACTIVE;
1691         }
1692     }
1693
1694   if (state_type == GTK_STATE_ACTIVE)
1695     {
1696       if (GTK_IS_TOGGLE_BUTTON (widget))
1697         {
1698           DrawEdge (dc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1699           SetTextColor (dc, GetSysColor (COLOR_3DHILIGHT));
1700           SetBkColor (dc, GetSysColor (COLOR_BTNFACE));
1701           FillRect (dc, &rect, get_dither_brush ());
1702         }
1703       else
1704         {
1705           FrameRect (dc, &rect, GetSysColorBrush (COLOR_WINDOWFRAME));
1706           InflateRect (&rect, -1, -1);
1707           FrameRect (dc, &rect, GetSysColorBrush (COLOR_BTNSHADOW));
1708           InflateRect (&rect, -1, -1);
1709           FillRect (dc, &rect, GetSysColorBrush (COLOR_BTNFACE));
1710         }
1711     }
1712   else
1713     {
1714       if (is_default || gtk_widget_has_focus (widget))
1715         {
1716           FrameRect (dc, &rect, GetSysColorBrush (COLOR_WINDOWFRAME));
1717           InflateRect (&rect, -1, -1);
1718         }
1719
1720       DrawFrameControl (dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH);
1721     }
1722
1723   release_window_dc (&dc_info);
1724 }
1725
1726 static void
1727 draw_box (GtkStyle *style,
1728           cairo_t *cr,
1729           GtkStateType state_type,
1730           GtkShadowType shadow_type,
1731           GtkWidget *widget,
1732           const gchar *detail, gint x, gint y, gint width, gint height)
1733 {
1734   if (is_combo_box_child (widget) && detail && !strcmp (detail, "button"))
1735     {
1736       RECT rect;
1737       XpDCInfo dc_info;
1738       DWORD border;
1739       HDC dc;
1740       int cx;
1741
1742       border = (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)) ? DFCS_PUSHED | DFCS_FLAT : 0);
1743
1744       dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
1745       DrawFrameControl (dc, &rect, DFC_SCROLL, DFCS_SCROLLDOWN | border);
1746       release_window_dc (&dc_info);
1747
1748       if (xp_theme_is_active ()
1749           && xp_theme_draw (cr, XP_THEME_ELEMENT_COMBOBUTTON, style, x, y,
1750                             width, height, state_type))
1751         {
1752       cx = GetSystemMetrics(SM_CXVSCROLL);
1753       x += width - cx;
1754       width = cx;
1755
1756
1757       dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width - cx, height, &rect);
1758       FillRect (dc, &rect, GetSysColorBrush (COLOR_WINDOW));
1759       release_window_dc (&dc_info);
1760       return;
1761         }
1762     }
1763
1764   if (detail &&
1765       (!strcmp (detail, "button") || !strcmp (detail, "buttondefault")))
1766     {
1767       if (GTK_IS_TREE_VIEW (gtk_widget_get_parent (widget)))
1768       {
1769         if (xp_theme_draw
1770               (cr, XP_THEME_ELEMENT_LIST_HEADER, style, x, y,
1771                width, height, state_type))
1772             {
1773               return;
1774             }
1775           else
1776             {
1777               HDC dc;
1778               RECT rect;
1779               XpDCInfo dc_info;
1780               dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
1781
1782               DrawFrameControl (dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH |
1783                                 (state_type ==
1784                                  GTK_STATE_ACTIVE ? (DFCS_PUSHED | DFCS_FLAT)
1785                                  : 0));
1786               release_window_dc (&dc_info);
1787             }
1788         }
1789       else if (is_toolbar_child (gtk_widget_get_parent (widget))
1790                || (!GTK_IS_BUTTON (widget) ||
1791                    (GTK_RELIEF_NONE == gtk_button_get_relief (GTK_BUTTON (widget)))))
1792         {
1793           if (draw_tool_button (cr, widget, style, x, y,
1794                                 width, height, state_type))
1795             {
1796               return;
1797             }
1798         }
1799       else
1800         {
1801           gboolean is_default = gtk_widget_has_default (widget);
1802           if (xp_theme_draw
1803               (cr,
1804                is_default ? XP_THEME_ELEMENT_DEFAULT_BUTTON :
1805                XP_THEME_ELEMENT_BUTTON, style, x, y, width, height,
1806                state_type))
1807             {
1808               return;
1809             }
1810
1811           draw_push_button (cr, widget, style,
1812                             x, y, width, height, state_type, is_default);
1813
1814           return;
1815         }
1816
1817       return;
1818     }
1819   else if (detail && !strcmp (detail, "spinbutton"))
1820     {
1821       if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1822         {
1823           return;
1824         }
1825     }
1826   else if (detail && (!strcmp (detail, "spinbutton_up")
1827                       || !strcmp (detail, "spinbutton_down")))
1828     {
1829       if (!xp_theme_draw (cr,
1830                           (!strcmp (detail, "spinbutton_up"))
1831                           ? XP_THEME_ELEMENT_SPIN_BUTTON_UP
1832                           : XP_THEME_ELEMENT_SPIN_BUTTON_DOWN,
1833                           style, x, y, width, height, state_type))
1834         {
1835           RECT rect;
1836           XpDCInfo dc_info;
1837           HDC dc;
1838
1839           dc = get_window_dc (style, cr, state_type, &dc_info,
1840                               x, y, width, height, &rect);
1841           DrawEdge (dc, &rect,
1842                     state_type ==
1843                     GTK_STATE_ACTIVE ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT);
1844           release_window_dc (&dc_info);
1845         }
1846       return;
1847     }
1848   else if (detail && !strcmp (detail, "slider"))
1849     {
1850       if (GTK_IS_SCROLLBAR (widget))
1851         {
1852           GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
1853           gboolean is_v = GTK_IS_VSCROLLBAR (widget);
1854
1855           if (xp_theme_draw (cr,
1856                              is_v
1857                              ? XP_THEME_ELEMENT_SCROLLBAR_V
1858                              : XP_THEME_ELEMENT_SCROLLBAR_H,
1859                              style, x, y, width, height, state_type))
1860             {
1861               XpThemeElement gripper =
1862                 (is_v ? XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V :
1863                  XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H);
1864
1865               /* Do not display grippers on tiny scroll bars,
1866                  the limit imposed is rather arbitrary, perhaps
1867                  we can fetch the gripper geometry from
1868                  somewhere and use that... */
1869               if ((gripper ==
1870                    XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H
1871                    && width < 16)
1872                   || (gripper ==
1873                       XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V && height < 16))
1874                 {
1875                   return;
1876                 }
1877
1878               xp_theme_draw (cr, gripper, style, x, y,
1879                              width, height, state_type);
1880               return;
1881             }
1882           else
1883             {
1884               if (gtk_range_get_adjustment(&scrollbar->range)->page_size >=
1885                   (gtk_range_get_adjustment(&scrollbar->range)->upper -
1886                    gtk_range_get_adjustment(&scrollbar->range)->lower))
1887                 {
1888                   return;
1889                 }
1890             }
1891         }
1892     }
1893   else if (detail && !strcmp (detail, "bar"))
1894     {
1895       if (widget && GTK_IS_PROGRESS_BAR (widget))
1896         {
1897           GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
1898           XpThemeElement xp_progress_bar =
1899             map_gtk_progress_bar_to_xp (progress_bar, FALSE);
1900
1901           if (xp_theme_draw (cr, xp_progress_bar, style, x, y,
1902                              width, height, state_type))
1903             {
1904               return;
1905             }
1906
1907           shadow_type = GTK_SHADOW_NONE;
1908         }
1909     }
1910   else if (detail && strcmp (detail, "menuitem") == 0)
1911     {
1912       shadow_type = GTK_SHADOW_NONE;
1913       if (draw_menu_item (cr, widget, style,
1914                           x, y, width, height, state_type))
1915         {
1916           return;
1917         }
1918     }
1919   else if (detail && !strcmp (detail, "trough"))
1920     {
1921       if (widget && GTK_IS_PROGRESS_BAR (widget))
1922         {
1923           GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
1924           XpThemeElement xp_progress_bar =
1925             map_gtk_progress_bar_to_xp (progress_bar, TRUE);
1926           if (xp_theme_draw
1927               (cr, xp_progress_bar, style, x, y, width, height,
1928                state_type))
1929             {
1930               return;
1931             }
1932           else
1933             {
1934               /* Blank in classic Windows */
1935             }
1936         }
1937       else if (widget && GTK_IS_SCROLLBAR (widget))
1938         {
1939           gboolean is_vertical = GTK_IS_VSCROLLBAR (widget);
1940
1941           if (xp_theme_draw (cr,
1942                              is_vertical
1943                              ? XP_THEME_ELEMENT_TROUGH_V
1944                              : XP_THEME_ELEMENT_TROUGH_H,
1945                              style, x, y, width, height, state_type))
1946             {
1947               return;
1948             }
1949           else
1950             {
1951               HDC dc;
1952               RECT rect;
1953               XpDCInfo dc_info;
1954
1955               dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
1956
1957               SetTextColor (dc, GetSysColor (COLOR_3DHILIGHT));
1958               SetBkColor (dc, GetSysColor (COLOR_BTNFACE));
1959               FillRect (dc, &rect, get_dither_brush ());
1960
1961               release_window_dc (&dc_info);
1962
1963               return;
1964             }
1965         }
1966       else if (widget && GTK_IS_SCALE (widget))
1967         {
1968           gboolean is_vertical = GTK_IS_VSCALE (widget);
1969
1970           if (!xp_theme_is_active ())
1971             {
1972               parent_class->draw_box (style, cr, state_type,
1973                                       GTK_SHADOW_NONE,
1974                                       widget, detail, x, y, width, height);
1975             }
1976
1977           if (is_vertical)
1978             {
1979               if (xp_theme_draw
1980                   (cr, XP_THEME_ELEMENT_SCALE_TROUGH_V,
1981                    style, (2 * x + width) / 2, y, 2, height,
1982                    state_type))
1983                 {
1984                   return;
1985                 }
1986
1987               parent_class->draw_box (style, cr, state_type,
1988                                       GTK_SHADOW_ETCHED_IN,
1989                                       NULL, NULL,
1990                                       (2 * x + width) / 2, y, 1, height);
1991             }
1992           else
1993             {
1994               if (xp_theme_draw
1995                   (cr, XP_THEME_ELEMENT_SCALE_TROUGH_H,
1996                    style, x, (2 * y + height) / 2, width, 2,
1997                    state_type))
1998                 {
1999                   return;
2000                 }
2001
2002               parent_class->draw_box (style, cr, state_type,
2003                                       GTK_SHADOW_ETCHED_IN,
2004                                       NULL, NULL, x,
2005                                       (2 * y + height) / 2, width, 1);
2006             }
2007
2008           return;
2009         }
2010     }
2011   else if (detail && strcmp (detail, "optionmenu") == 0)
2012     {
2013       if (xp_theme_draw (cr, XP_THEME_ELEMENT_EDIT_TEXT,
2014                          style, x, y, width, height, state_type))
2015         {
2016           return;
2017         }
2018     }
2019   else if (detail
2020            && (strcmp (detail, "vscrollbar") == 0
2021                || strcmp (detail, "hscrollbar") == 0))
2022     {
2023       return;
2024     }
2025   else if (detail
2026            && (strcmp (detail, "handlebox_bin") == 0
2027                || strcmp (detail, "toolbar") == 0
2028                || strcmp (detail, "menubar") == 0))
2029     {
2030       if (xp_theme_draw (cr, XP_THEME_ELEMENT_REBAR,
2031                          style, x, y, width, height, state_type))
2032         {
2033           return;
2034         }
2035     }
2036   else if (detail && (!strcmp (detail, "handlebox")))   /* grip */
2037     {
2038       if (!xp_theme_is_active ())
2039         {
2040           return;
2041         }
2042     }
2043   else if (detail && !strcmp (detail, "notebook") && GTK_IS_NOTEBOOK (widget))
2044     {
2045       if (xp_theme_draw (cr, XP_THEME_ELEMENT_TAB_PANE, style,
2046                          x, y, width, height, state_type))
2047         {
2048           return;
2049         }
2050     }
2051
2052   else
2053     {
2054       const gchar *name = gtk_widget_get_name (widget);
2055
2056       if (name && !strcmp (name, "gtk-tooltips"))
2057         {
2058           if (xp_theme_draw
2059               (cr, XP_THEME_ELEMENT_TOOLTIP, style, x, y, width,
2060                height, state_type))
2061             {
2062               return;
2063             }
2064           else
2065             {
2066               HBRUSH brush;
2067               RECT rect;
2068               XpDCInfo dc_info;
2069               HDC hdc;
2070
2071               hdc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
2072
2073               brush = GetSysColorBrush (COLOR_3DDKSHADOW);
2074
2075               if (brush)
2076                 {
2077                   FrameRect (hdc, &rect, brush);
2078                 }
2079
2080               InflateRect (&rect, -1, -1);
2081               FillRect (hdc, &rect, (HBRUSH) (COLOR_INFOBK + 1));
2082
2083               release_window_dc (&dc_info);
2084
2085               return;
2086             }
2087         }
2088     }
2089
2090   parent_class->draw_box (style, cr, state_type, shadow_type,
2091                           widget, detail, x, y, width, height);
2092
2093   if (detail && strcmp (detail, "optionmenu") == 0)
2094     {
2095       GtkRequisition indicator_size;
2096       GtkBorder indicator_spacing;
2097       gint vline_x;
2098
2099       option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2100
2101       if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
2102         {
2103           vline_x =
2104             x + indicator_size.width + indicator_spacing.left +
2105             indicator_spacing.right;
2106         }
2107       else
2108         {
2109           vline_x = x + width - (indicator_size.width +
2110                                  indicator_spacing.left +
2111                                  indicator_spacing.right) - style->xthickness;
2112
2113           parent_class->draw_vline (style, cr, state_type, widget,
2114                                     detail,
2115                                     y + style->ythickness + 1,
2116                                     y + height - style->ythickness - 3, vline_x);
2117         }
2118     }
2119 }
2120
2121 static void
2122 draw_tab (GtkStyle *style,
2123           cairo_t *cr,
2124           GtkStateType state,
2125           GtkShadowType shadow,
2126           GtkWidget *widget,
2127           const gchar *detail, gint x, gint y, gint width, gint height)
2128 {
2129   GtkRequisition indicator_size;
2130   GtkBorder indicator_spacing;
2131
2132   gint arrow_height;
2133
2134   g_return_if_fail (style != NULL);
2135   g_return_if_fail (cr != NULL);
2136
2137   if (detail && !strcmp (detail, "optionmenutab"))
2138     {
2139       GtkAllocation allocation;
2140
2141       gtk_widget_get_allocation (widget, &allocation);
2142       if (xp_theme_draw (cr, XP_THEME_ELEMENT_COMBOBUTTON,
2143                          style, x - 5, allocation.y + 1,
2144                          width + 10, allocation.height - 2,
2145                          state))
2146         {
2147           return;
2148         }
2149     }
2150
2151   option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2152
2153   x += (width - indicator_size.width) / 2;
2154   arrow_height = (indicator_size.width + 1) / 2;
2155
2156   y += (height - arrow_height) / 2;
2157
2158   draw_varrow (cr, &style->black, shadow, GTK_ARROW_DOWN,
2159                x, y, indicator_size.width, arrow_height);
2160 }
2161
2162 /* Draw classic Windows tab - thanks Mozilla!
2163   (no system API for this, but DrawEdge can draw all the parts of a tab) */
2164 static void
2165 DrawTab (HDC hdc, const RECT R, gint32 aPosition, gboolean aSelected,
2166          gboolean aDrawLeft, gboolean aDrawRight)
2167 {
2168   gint32 leftFlag, topFlag, rightFlag, lightFlag, shadeFlag;
2169   RECT topRect, sideRect, bottomRect, lightRect, shadeRect;
2170   gint32 selectedOffset, lOffset, rOffset;
2171
2172   selectedOffset = aSelected ? 1 : 0;
2173   lOffset = aDrawLeft ? 2 : 0;
2174   rOffset = aDrawRight ? 2 : 0;
2175
2176   /* Get info for tab orientation/position (Left, Top, Right, Bottom) */
2177   switch (aPosition)
2178     {
2179     case BF_LEFT:
2180       leftFlag = BF_TOP;
2181       topFlag = BF_LEFT;
2182       rightFlag = BF_BOTTOM;
2183       lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
2184       shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
2185
2186       SetRect (&topRect, R.left, R.top + lOffset, R.right,
2187                R.bottom - rOffset);
2188       SetRect (&sideRect, R.left + 2, R.top, R.right - 2 + selectedOffset,
2189                R.bottom);
2190       SetRect (&bottomRect, R.right - 2, R.top, R.right, R.bottom);
2191       SetRect (&lightRect, R.left, R.top, R.left + 3, R.top + 3);
2192       SetRect (&shadeRect, R.left + 1, R.bottom - 2, R.left + 2,
2193                R.bottom - 1);
2194       break;
2195
2196     case BF_TOP:
2197       leftFlag = BF_LEFT;
2198       topFlag = BF_TOP;
2199       rightFlag = BF_RIGHT;
2200       lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
2201       shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
2202
2203       SetRect (&topRect, R.left + lOffset, R.top, R.right - rOffset,
2204                R.bottom);
2205       SetRect (&sideRect, R.left, R.top + 2, R.right,
2206                R.bottom - 1 + selectedOffset);
2207       SetRect (&bottomRect, R.left, R.bottom - 1, R.right, R.bottom);
2208       SetRect (&lightRect, R.left, R.top, R.left + 3, R.top + 3);
2209       SetRect (&shadeRect, R.right - 2, R.top + 1, R.right - 1, R.top + 2);
2210       break;
2211
2212     case BF_RIGHT:
2213       leftFlag = BF_TOP;
2214       topFlag = BF_RIGHT;
2215       rightFlag = BF_BOTTOM;
2216       lightFlag = BF_DIAGONAL_ENDTOPLEFT;
2217       shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
2218
2219       SetRect (&topRect, R.left, R.top + lOffset, R.right,
2220                R.bottom - rOffset);
2221       SetRect (&sideRect, R.left + 2 - selectedOffset, R.top, R.right - 2,
2222                R.bottom);
2223       SetRect (&bottomRect, R.left, R.top, R.left + 2, R.bottom);
2224       SetRect (&lightRect, R.right - 3, R.top, R.right - 1, R.top + 2);
2225       SetRect (&shadeRect, R.right - 2, R.bottom - 3, R.right, R.bottom - 1);
2226       break;
2227
2228     case BF_BOTTOM:
2229       leftFlag = BF_LEFT;
2230       topFlag = BF_BOTTOM;
2231       rightFlag = BF_RIGHT;
2232       lightFlag = BF_DIAGONAL_ENDTOPLEFT;
2233       shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
2234
2235       SetRect (&topRect, R.left + lOffset, R.top, R.right - rOffset,
2236                R.bottom);
2237       SetRect (&sideRect, R.left, R.top + 2 - selectedOffset, R.right,
2238                R.bottom - 2);
2239       SetRect (&bottomRect, R.left, R.top, R.right, R.top + 2);
2240       SetRect (&lightRect, R.left, R.bottom - 3, R.left + 2, R.bottom - 1);
2241       SetRect (&shadeRect, R.right - 2, R.bottom - 3, R.right, R.bottom - 1);
2242       break;
2243
2244     default:
2245       g_return_if_reached ();
2246     }
2247
2248   /* Background */
2249   FillRect (hdc, &R, (HBRUSH) (COLOR_3DFACE + 1));
2250
2251   /* Tab "Top" */
2252   DrawEdge (hdc, &topRect, EDGE_RAISED, BF_SOFT | topFlag);
2253
2254   /* Tab "Bottom" */
2255   if (!aSelected)
2256     DrawEdge (hdc, &bottomRect, EDGE_RAISED, BF_SOFT | topFlag);
2257
2258   /* Tab "Sides" */
2259   if (!aDrawLeft)
2260     leftFlag = 0;
2261   if (!aDrawRight)
2262     rightFlag = 0;
2263
2264   DrawEdge (hdc, &sideRect, EDGE_RAISED, BF_SOFT | leftFlag | rightFlag);
2265
2266   /* Tab Diagonal Corners */
2267   if (aDrawLeft)
2268     DrawEdge (hdc, &lightRect, EDGE_RAISED, BF_SOFT | lightFlag);
2269
2270   if (aDrawRight)
2271     DrawEdge (hdc, &shadeRect, EDGE_RAISED, BF_SOFT | shadeFlag);
2272 }
2273
2274 static gboolean
2275 draw_themed_tab_button (GtkStyle *style,
2276                         cairo_t *cr,
2277                         GtkStateType state_type,
2278                         GtkNotebook *notebook,
2279                         gint x, gint y,
2280                         gint width, gint height, gint gap_side)
2281 {
2282 /* FIXME: poop
2283   GdkPixmap *pixmap = NULL;
2284  */
2285   gint border_width =
2286     gtk_container_get_border_width (GTK_CONTAINER (notebook));
2287   GtkWidget *widget = GTK_WIDGET (notebook);
2288   GdkRectangle draw_rect;
2289   GdkPixbufRotation rotation = GDK_PIXBUF_ROTATE_NONE;
2290   GtkAllocation allocation;
2291
2292   gtk_widget_get_allocation (widget, &allocation);
2293
2294   if (gap_side == GTK_POS_TOP)
2295     {
2296       int widget_right;
2297
2298       if (state_type == GTK_STATE_NORMAL)
2299         {
2300           draw_rect.x = x;
2301           draw_rect.y = y;
2302           draw_rect.width = width + 2;
2303           draw_rect.height = height;
2304
2305 /* FIXME: wtf?
2306           clip_rect.height--;
2307  */
2308         }
2309       else
2310         {
2311           draw_rect.x = x + 2;
2312           draw_rect.y = y;
2313           draw_rect.width = width - 2;
2314           draw_rect.height = height - 2;
2315         }
2316
2317       /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */
2318       widget_right = allocation.x + allocation.width - border_width - 2;
2319
2320       if (draw_rect.x + draw_rect.width >= widget_right)
2321         {
2322           draw_rect.width = widget_right - draw_rect.x;
2323         }
2324     }
2325   if (gap_side == GTK_POS_BOTTOM)
2326     {
2327       int widget_right;
2328
2329       if (state_type == GTK_STATE_NORMAL)
2330         {
2331           draw_rect.x = x;
2332           draw_rect.y = y;
2333           draw_rect.width = width + 2;
2334           draw_rect.height = height;
2335         }
2336       else
2337         {
2338           draw_rect.x = x + 2;
2339           draw_rect.y = y + 2;
2340           draw_rect.width = width - 2;
2341           draw_rect.height = height - 2;
2342         }
2343
2344       /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */
2345       widget_right = allocation.x + allocation.width - border_width - 2;
2346
2347       if (draw_rect.x + draw_rect.width >= widget_right)
2348         {
2349           draw_rect.width = widget_right - draw_rect.x;
2350         }
2351
2352       rotation = GDK_PIXBUF_ROTATE_UPSIDEDOWN;
2353     }
2354   else if (gap_side == GTK_POS_LEFT)
2355     {
2356       int widget_bottom;
2357
2358       if (state_type == GTK_STATE_NORMAL)
2359         {
2360           draw_rect.x = x;
2361           draw_rect.y = y;
2362           draw_rect.width = width;
2363           draw_rect.height = height + 2;
2364
2365 /* FIXME: wtf?
2366           clip_rect.width--;
2367  */
2368         }
2369       else
2370         {
2371           draw_rect.x = x;
2372           draw_rect.y = y + 2;
2373           draw_rect.width = width - 2;
2374           draw_rect.height = height - 2;
2375         }
2376
2377       /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */
2378       widget_bottom = allocation.x + allocation.height - border_width - 2;
2379
2380       if (draw_rect.y + draw_rect.height >= widget_bottom)
2381         {
2382           draw_rect.height = widget_bottom - draw_rect.y;
2383         }
2384
2385       rotation = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
2386     }
2387   else if (gap_side == GTK_POS_RIGHT)
2388     {
2389       int widget_bottom;
2390
2391       if (state_type == GTK_STATE_NORMAL)
2392         {
2393           draw_rect.x = x + 1;
2394           draw_rect.y = y;
2395           draw_rect.width = width;
2396           draw_rect.height = height + 2;
2397
2398 /* FIXME: wtf?
2399           clip_rect.width--;
2400  */
2401         }
2402       else
2403         {
2404           draw_rect.x = x + 2;
2405           draw_rect.y = y + 2;
2406           draw_rect.width = width - 2;
2407           draw_rect.height = height - 2;
2408         }
2409
2410       /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */
2411       widget_bottom = allocation.x + allocation.height - border_width - 2;
2412
2413       if (draw_rect.y + draw_rect.height >= widget_bottom)
2414         {
2415           draw_rect.height = widget_bottom - draw_rect.y;
2416         }
2417
2418       rotation = GDK_PIXBUF_ROTATE_CLOCKWISE;
2419     }
2420
2421   if (gap_side == GTK_POS_TOP)
2422     {
2423       if (!xp_theme_draw (cr, XP_THEME_ELEMENT_TAB_ITEM, style,
2424                           draw_rect.x, draw_rect.y,
2425                           draw_rect.width, draw_rect.height,
2426                           state_type))
2427         {
2428           return FALSE;
2429         }
2430     }
2431   else
2432     {
2433 /* FIXME: poop */
2434 #if 0
2435       GdkPixbuf *pixbuf;
2436       GdkPixbuf *rotated;
2437
2438       if (gap_side == GTK_POS_LEFT || gap_side == GTK_POS_RIGHT)
2439         {
2440           pixmap = gdk_pixmap_new (cr, draw_rect.height, draw_rect.width, -1);
2441
2442           if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style,
2443 /* FIXME: wtf? */
2444                               draw_rect.y - draw_rect.y, draw_rect.x - draw_rect.x,
2445                               draw_rect.height, draw_rect.width, state_type, 0))
2446             {
2447               g_object_unref (pixmap);
2448               return FALSE;
2449             }
2450
2451           pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0,
2452                                                  draw_rect.height, draw_rect.width);
2453           g_object_unref (pixmap);
2454         }
2455       else
2456         {
2457           pixmap = gdk_pixmap_new (cr, draw_rect.width, draw_rect.height, -1);
2458
2459           if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style,
2460 /* FIXME: wtf? */
2461                               draw_rect.x - draw_rect.x, draw_rect.y - draw_rect.y,
2462                               draw_rect.width, draw_rect.height, state_type, 0))
2463             {
2464               g_object_unref (pixmap);
2465               return FALSE;
2466             }
2467
2468           pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0,
2469                                                  draw_rect.width, draw_rect.height);
2470           g_object_unref (pixmap);
2471         }
2472
2473       rotated = gdk_pixbuf_rotate_simple (pixbuf, rotation);
2474       g_object_unref (pixbuf);
2475       pixbuf = rotated;
2476
2477       // XXX - This is really hacky and evil.  When we're drawing the left-most tab
2478       //       while it is active on a bottom-oriented notebook, there is one white
2479       //       pixel at the top.  There may be a better solution than this if someone
2480       //       has time to discover it.
2481       if (gap_side == GTK_POS_BOTTOM && state_type == GTK_STATE_NORMAL
2482           && x == allocation.x)
2483         {
2484           int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
2485           int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
2486           int psub = 0;
2487
2488           guchar *pixels = gdk_pixbuf_get_pixels (pixbuf);
2489           guchar *p = pixels + rowstride;
2490
2491           for (psub = 0; psub < n_channels; psub++)
2492             {
2493               pixels[psub] = p[psub];
2494             }
2495         }
2496
2497       gdk_cairo_set_source_pixbuf (cr, pixbuf, clip_rect.x, clip_rect.y);
2498       cairo_paint (cr);
2499       g_object_unref (pixbuf);
2500 #endif
2501     }
2502
2503   return TRUE;
2504 }
2505
2506 static gboolean
2507 draw_tab_button (GtkStyle *style,
2508                  cairo_t *cr,
2509                  GtkStateType state_type,
2510                  GtkShadowType shadow_type,
2511                  GtkWidget *widget,
2512                  const gchar *detail,
2513                  gint x, gint y, gint width, gint height, gint gap_side)
2514 {
2515   if (gap_side == GTK_POS_TOP || gap_side == GTK_POS_BOTTOM)
2516     {
2517       /* experimental tab-drawing code from mozilla */
2518       RECT rect;
2519       XpDCInfo dc_info;
2520       HDC dc;
2521       gint32 aPosition;
2522
2523       dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
2524
2525       if (gap_side == GTK_POS_TOP)
2526         aPosition = BF_TOP;
2527       else if (gap_side == GTK_POS_BOTTOM)
2528         aPosition = BF_BOTTOM;
2529       else if (gap_side == GTK_POS_LEFT)
2530         aPosition = BF_LEFT;
2531       else
2532         aPosition = BF_RIGHT;
2533
2534       if (state_type == GTK_STATE_PRELIGHT)
2535         state_type = GTK_STATE_NORMAL;
2536
2537 /* FIXME: wtf? 
2538            gdk_cairo_set_source_color (cr, &style->dark[state_type]);
2539  */
2540
2541       DrawTab (dc, rect, aPosition,
2542                state_type != GTK_STATE_PRELIGHT,
2543                (gap_side != GTK_POS_LEFT), (gap_side != GTK_POS_RIGHT));
2544
2545       release_window_dc (&dc_info);
2546
2547       return TRUE;
2548     }
2549
2550   return FALSE;
2551 }
2552
2553 static void
2554 draw_extension (GtkStyle *style,
2555                 cairo_t *cr,
2556                 GtkStateType state_type,
2557                 GtkShadowType shadow_type,
2558                 GtkWidget *widget,
2559                 const gchar *detail,
2560                 gint x, gint y,
2561                 gint width, gint height, GtkPositionType gap_side)
2562 {
2563   if (widget && GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "tab"))
2564     {
2565       GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2566
2567       /* Why this differs from gap_side, I have no idea.. */
2568       int real_gap_side = gtk_notebook_get_tab_pos (notebook);
2569
2570       if (!draw_themed_tab_button (style, cr, state_type,
2571                                    GTK_NOTEBOOK (widget), x, y,
2572                                    width, height, real_gap_side))
2573         {
2574           if (!draw_tab_button (style, cr, state_type,
2575                                 shadow_type, widget,
2576                                 detail, x, y, width, height, real_gap_side))
2577             {
2578               parent_class->draw_extension (style, cr, state_type,
2579                                             shadow_type, widget, detail,
2580                                             x, y, width, height,
2581                                             real_gap_side);
2582             }
2583         }
2584     }
2585 }
2586
2587 static void
2588 draw_box_gap (GtkStyle *style, cairo_t *cr, GtkStateType state_type,
2589               GtkShadowType shadow_type,
2590               GtkWidget *widget, const gchar *detail, gint x,
2591               gint y, gint width, gint height, GtkPositionType gap_side,
2592               gint gap_x, gint gap_width)
2593 {
2594   if (GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "notebook"))
2595     {
2596       GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2597       int side = gtk_notebook_get_tab_pos (notebook);
2598       int x2 = x, y2 = y, w2 = width, h2 = height;
2599
2600       if (side == GTK_POS_TOP)
2601         {
2602           x2 = x;
2603           y2 = y - gtk_notebook_get_tab_vborder (notebook);
2604           w2 = width;
2605           h2 = height + gtk_notebook_get_tab_vborder (notebook) * 2;
2606         }
2607       else if (side == GTK_POS_BOTTOM)
2608         {
2609           x2 = x;
2610           y2 = y;
2611           w2 = width;
2612           h2 = height + gtk_notebook_get_tab_vborder (notebook) * 2;
2613         }
2614       else if (side == GTK_POS_LEFT)
2615         {
2616           x2 = x - gtk_notebook_get_tab_hborder (notebook);
2617           y2 = y;
2618           w2 = width + gtk_notebook_get_tab_hborder (notebook);
2619           h2 = height;
2620         }
2621       else if (side == GTK_POS_RIGHT)
2622         {
2623           x2 = x;
2624           y2 = y;
2625           w2 = width + gtk_notebook_get_tab_hborder (notebook) * 2;
2626           h2 = height;
2627         }
2628
2629       if (xp_theme_draw (cr, XP_THEME_ELEMENT_TAB_PANE, style,
2630                          x2, y2, w2, h2, state_type))
2631         {
2632           return;
2633         }
2634     }
2635
2636   parent_class->draw_box_gap (style, cr, state_type, shadow_type,
2637                               widget, detail, x, y, width, height,
2638                               gap_side, gap_x, gap_width);
2639 }
2640
2641 static gboolean
2642 is_popup_window_child (GtkWidget *widget)
2643 {
2644   GtkWidget *top;
2645   GtkWindowType type = -1;
2646
2647   top = gtk_widget_get_toplevel (widget);
2648
2649   if (top && GTK_IS_WINDOW (top))
2650     {
2651       g_object_get (top, "type", &type, NULL);
2652
2653       if (type == GTK_WINDOW_POPUP)
2654         {                       /* Hack for combo boxes */
2655           return TRUE;
2656         }
2657     }
2658
2659   return FALSE;
2660 }
2661
2662 static void
2663 draw_flat_box (GtkStyle *style, cairo_t *cr,
2664                GtkStateType state_type, GtkShadowType shadow_type,
2665                GtkWidget *widget,
2666                const gchar *detail, gint x, gint y, gint width, gint height)
2667 {
2668   if (detail)
2669     {
2670       if (state_type == GTK_STATE_SELECTED &&
2671           (!strncmp ("cell_even", detail, 9) || !strncmp ("cell_odd", detail, 8)))
2672         {
2673           GdkColor *gc = gtk_widget_has_focus (widget) ? &style->base[state_type] : &style->base[GTK_STATE_ACTIVE];
2674
2675           _cairo_draw_rectangle (cr, gc, TRUE, x, y, width, height);
2676
2677           return;
2678         }
2679       else if (!strcmp (detail, "checkbutton"))
2680         {
2681           if (state_type == GTK_STATE_PRELIGHT)
2682             {
2683               return;
2684             }
2685         }
2686     }
2687
2688   parent_class->draw_flat_box (style, cr, state_type, shadow_type,
2689                                widget, detail, x, y, width, height);
2690 }
2691
2692 static gboolean
2693 draw_menu_border (cairo_t *cr, GtkStyle *style,
2694                   gint x, gint y, gint width, gint height)
2695 {
2696   RECT rect;
2697   XpDCInfo dc_info;
2698   HDC dc;
2699
2700   dc = get_window_dc (style, cr, GTK_STATE_NORMAL, &dc_info, x, y, width, height, &rect);
2701
2702   if (!dc)
2703     return FALSE;
2704
2705   if (xp_theme_is_active ())
2706     {
2707       FrameRect (dc, &rect, GetSysColorBrush (COLOR_3DSHADOW));
2708     }
2709   else
2710     {
2711       DrawEdge (dc, &rect, EDGE_RAISED, BF_RECT);
2712     }
2713
2714   release_window_dc (&dc_info);
2715
2716   return TRUE;
2717 }
2718
2719 static void
2720 draw_shadow (GtkStyle *style,
2721              cairo_t *cr,
2722              GtkStateType state_type,
2723              GtkShadowType shadow_type,
2724              GtkWidget *widget,
2725              const gchar *detail, gint x, gint y, gint width, gint height)
2726 {
2727   gboolean is_handlebox;
2728   gboolean is_toolbar;
2729
2730   if (detail && !strcmp (detail, "frame"))
2731     {
2732
2733       HDC dc;
2734       RECT rect;
2735       XpDCInfo dc_info;
2736
2737
2738
2739       dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
2740       if (is_combo_box_child (widget))
2741         {
2742           FillRect (dc, &rect, GetSysColorBrush (COLOR_WINDOW));
2743         }
2744       else if (is_popup_window_child (widget))
2745         {
2746           FrameRect (dc, &rect, GetSysColorBrush (COLOR_WINDOWFRAME));
2747         }
2748       else
2749         {
2750           switch (shadow_type)
2751             {
2752             case GTK_SHADOW_IN:
2753               draw_3d_border (dc, &rect, TRUE);
2754               break;
2755
2756             case GTK_SHADOW_OUT:
2757               draw_3d_border (dc, &rect, FALSE);
2758               break;
2759
2760             case GTK_SHADOW_ETCHED_IN:
2761               draw_3d_border (dc, &rect, TRUE);
2762               InflateRect (&rect, -1, -1);
2763               draw_3d_border (dc, &rect, FALSE);
2764               break;
2765
2766             case GTK_SHADOW_ETCHED_OUT:
2767               draw_3d_border (dc, &rect, FALSE);
2768               InflateRect (&rect, -1, -1);
2769               draw_3d_border (dc, &rect, TRUE);
2770               break;
2771
2772             case GTK_SHADOW_NONE:
2773               break;
2774             }
2775         }
2776
2777       release_window_dc (&dc_info);
2778
2779       return;
2780     }
2781   if (detail && (!strcmp (detail, "entry") || !strcmp (detail, "combobox")))
2782     {
2783       if (shadow_type != GTK_SHADOW_IN)
2784         return;
2785
2786       if (!xp_theme_draw (cr, XP_THEME_ELEMENT_EDIT_TEXT, style,
2787                           x, y, width, height, state_type))
2788         {
2789           HDC dc;
2790           RECT rect;
2791           XpDCInfo dc_info;
2792
2793           dc = get_window_dc (style, cr, state_type, &dc_info,
2794                               x, y, width, height, &rect);
2795
2796           DrawEdge (dc, &rect, EDGE_SUNKEN, BF_RECT);
2797           release_window_dc (&dc_info);
2798         }
2799
2800       return;
2801     }
2802
2803   if (detail && !strcmp (detail, "scrolled_window") &&
2804       xp_theme_draw (cr, XP_THEME_ELEMENT_EDIT_TEXT, style,
2805                      x, y, width, height, state_type))
2806     {
2807       return;
2808     }
2809
2810   if (detail && !strcmp (detail, "spinbutton"))
2811     return;
2812
2813   if (detail && !strcmp (detail, "menu"))
2814     {
2815       if (draw_menu_border (cr, style, x, y, width, height))
2816         {
2817           return;
2818         }
2819     }
2820
2821   if (detail && !strcmp (detail, "handlebox"))
2822     return;
2823
2824   is_handlebox = (detail && !strcmp (detail, "handlebox_bin"));
2825   is_toolbar = (detail
2826                 && (!strcmp (detail, "toolbar")
2827                     || !strcmp (detail, "menubar")));
2828
2829   if (is_toolbar || is_handlebox)
2830     {
2831       if (shadow_type == GTK_SHADOW_NONE)
2832         {
2833           return;
2834         }
2835
2836       if (widget)
2837         {
2838           HDC dc;
2839           RECT rect;
2840           XpDCInfo dc_info;
2841           HGDIOBJ old_pen = NULL;
2842           GtkPositionType pos;
2843
2844           if (is_handlebox)
2845             {
2846               pos = gtk_handle_box_get_handle_position (GTK_HANDLE_BOX (widget));
2847               /*
2848                  If the handle box is at left side,
2849                  we shouldn't draw its right border.
2850                  The same holds true for top, right, and bottom.
2851                */
2852               switch (pos)
2853                 {
2854                 case GTK_POS_LEFT:
2855                   pos = GTK_POS_RIGHT;
2856                   break;
2857
2858                 case GTK_POS_RIGHT:
2859                   pos = GTK_POS_LEFT;
2860                   break;
2861
2862                 case GTK_POS_TOP:
2863                   pos = GTK_POS_BOTTOM;
2864                   break;
2865
2866                 case GTK_POS_BOTTOM:
2867                   pos = GTK_POS_TOP;
2868                   break;
2869                 }
2870             }
2871           else
2872             {
2873               GtkWidget *parent = gtk_widget_get_parent (widget);
2874
2875               /* Dirty hack for toolbars contained in handle boxes */
2876               if (GTK_IS_HANDLE_BOX (parent))
2877                 {
2878                   pos = gtk_handle_box_get_handle_position (GTK_HANDLE_BOX (parent));
2879                 }
2880               else
2881                 {
2882                   /*
2883                      Dirty hack:
2884                      Make pos != all legal enum vaules of GtkPositionType.
2885                      So every border will be draw.
2886                    */
2887                   pos = (GtkPositionType) - 1;
2888                 }
2889             }
2890
2891           dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
2892
2893           if (pos != GTK_POS_LEFT)
2894             {
2895               old_pen = SelectObject (dc, get_light_pen ());
2896               MoveToEx (dc, rect.left, rect.top, NULL);
2897               LineTo (dc, rect.left, rect.bottom);
2898             }
2899           if (pos != GTK_POS_TOP)
2900             {
2901               old_pen = SelectObject (dc, get_light_pen ());
2902               MoveToEx (dc, rect.left, rect.top, NULL);
2903               LineTo (dc, rect.right, rect.top);
2904             }
2905           if (pos != GTK_POS_RIGHT)
2906             {
2907               old_pen = SelectObject (dc, get_dark_pen ());
2908               MoveToEx (dc, rect.right - 1, rect.top, NULL);
2909               LineTo (dc, rect.right - 1, rect.bottom);
2910             }
2911           if (pos != GTK_POS_BOTTOM)
2912             {
2913               old_pen = SelectObject (dc, get_dark_pen ());
2914               MoveToEx (dc, rect.left, rect.bottom - 1, NULL);
2915               LineTo (dc, rect.right, rect.bottom - 1);
2916             }
2917           if (old_pen)
2918             SelectObject (dc, old_pen);
2919           release_window_dc (&dc_info);
2920         }
2921
2922       return;
2923     }
2924
2925   if (detail && !strcmp (detail, "statusbar"))
2926     {
2927       return;
2928     }
2929
2930   parent_class->draw_shadow (style, cr, state_type, shadow_type,
2931                              widget, detail, x, y, width, height);
2932 }
2933
2934 static void
2935 draw_hline (GtkStyle *style,
2936             cairo_t *cr,
2937             GtkStateType state_type,
2938             GtkWidget *widget,
2939             const gchar *detail, gint x1, gint x2, gint y)
2940 {
2941   if (xp_theme_is_active () && detail && !strcmp (detail, "menuitem"))
2942     {
2943       gint cx, cy;
2944       gint new_y, new_height;
2945       gint y_offset;
2946
2947       xp_theme_get_element_dimensions (XP_THEME_ELEMENT_MENU_SEPARATOR,
2948                                        state_type,
2949                                        &cx, &cy);
2950
2951       /* Center the separator */
2952       y_offset = (cy / 2) - 1;
2953       new_y = (y - y_offset) >= 0 ? y - y_offset : y;
2954       new_height = cy;
2955
2956       if (xp_theme_draw
2957           (cr, XP_THEME_ELEMENT_MENU_SEPARATOR, style, x1, new_y, x2, new_height,
2958            state_type))
2959         {
2960           return;
2961         }
2962       else
2963         {
2964           _cairo_draw_line (cr, &style->dark[state_type], x1, y, x2, y);
2965
2966         }
2967     }
2968   else
2969     {
2970       if (style->ythickness == 2)
2971         {
2972           _cairo_draw_line (cr, &style->dark[state_type], x1, y, x2, y);
2973           ++y;
2974           _cairo_draw_line (cr, &style->light[state_type], x1, y, x2, y);
2975
2976         }
2977       else
2978         {
2979           parent_class->draw_hline (style, cr, state_type, widget,
2980                                     detail, x1, x2, y);
2981         }
2982     }
2983 }
2984
2985 static void
2986 draw_vline (GtkStyle *style,
2987             cairo_t *cr,
2988             GtkStateType state_type,
2989             GtkWidget *widget,
2990             const gchar *detail, gint y1, gint y2, gint x)
2991 {
2992   if (style->xthickness == 2)
2993     {
2994       _cairo_draw_line (cr, &style->dark[state_type], x, y1, x, y2);
2995       ++x;
2996       _cairo_draw_line (cr, &style->light[state_type], x, y1, x, y2);
2997
2998     }
2999   else
3000     {
3001       parent_class->draw_vline (style, cr, state_type, widget,
3002                                 detail, y1, y2, x);
3003     }
3004 }
3005
3006 static void
3007 draw_slider (GtkStyle *style,
3008              cairo_t *cr,
3009              GtkStateType state_type,
3010              GtkShadowType shadow_type,
3011              GtkWidget *widget,
3012              const gchar *detail,
3013              gint x,
3014              gint y, gint width, gint height, GtkOrientation orientation)
3015 {
3016   if (GTK_IS_SCALE (widget) &&
3017       xp_theme_draw (cr, ((orientation == GTK_ORIENTATION_VERTICAL) ?
3018                               XP_THEME_ELEMENT_SCALE_SLIDER_V :
3019                               XP_THEME_ELEMENT_SCALE_SLIDER_H), style, x, y, width,
3020                      height, state_type))
3021     {
3022       return;
3023     }
3024
3025   parent_class->draw_slider (style, cr, state_type, shadow_type,
3026                              widget, detail, x, y, width, height,
3027                              orientation);
3028 }
3029
3030 static void
3031 draw_resize_grip (GtkStyle *style,
3032                   cairo_t *cr,
3033                   GtkStateType state_type,
3034                   GtkWidget *widget,
3035                   const gchar *detail,
3036                   GdkWindowEdge edge, gint x, gint y, gint width, gint height)
3037 {
3038   if (detail && !strcmp (detail, "statusbar"))
3039     {
3040       if (xp_theme_draw
3041           (cr, XP_THEME_ELEMENT_STATUS_GRIPPER, style, x, y, width,
3042            height, state_type))
3043         {
3044           return;
3045         }
3046       else
3047         {
3048           RECT rect;
3049           XpDCInfo dc_info;
3050           HDC dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
3051
3052 /* FIXME: wtf?
3053               gdk_cairo_set_source_color (cr, &style->dark[state_type]);
3054  */
3055
3056           DrawFrameControl (dc, &rect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
3057           release_window_dc (&dc_info);
3058
3059           return;
3060         }
3061     }
3062
3063   parent_class->draw_resize_grip (style, cr, state_type,
3064                                   widget, detail, edge, x, y, width, height);
3065 }
3066
3067 static void
3068 draw_handle (GtkStyle *style,
3069              cairo_t *cr,
3070              GtkStateType state_type,
3071              GtkShadowType shadow_type,
3072              GtkWidget *widget,
3073              const gchar *detail,
3074              gint x,
3075              gint y, gint width, gint height, GtkOrientation orientation)
3076 {
3077   HDC dc;
3078   RECT rect;
3079   XpDCInfo dc_info;
3080
3081   if (is_toolbar_child (widget))
3082     {
3083       XpThemeElement hndl;
3084
3085       if (GTK_IS_HANDLE_BOX (widget))
3086         {
3087           GtkPositionType pos;
3088           pos = gtk_handle_box_get_handle_position (GTK_HANDLE_BOX (widget));
3089
3090           if (pos == GTK_POS_TOP || pos == GTK_POS_BOTTOM)
3091             {
3092               orientation = GTK_ORIENTATION_HORIZONTAL;
3093             }
3094           else
3095             {
3096               orientation = GTK_ORIENTATION_VERTICAL;
3097             }
3098         }
3099
3100       if (orientation == GTK_ORIENTATION_VERTICAL)
3101         hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_V;
3102       else
3103         hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_H;
3104
3105       if (xp_theme_draw (cr, hndl, style, x, y, width, height,
3106                          state_type))
3107         {
3108           return;
3109         }
3110
3111       dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
3112
3113       if (orientation == GTK_ORIENTATION_VERTICAL)
3114         {
3115           rect.left += 3;
3116           rect.right = rect.left + 3;
3117           rect.bottom -= 3;
3118           rect.top += 3;
3119         }
3120       else
3121         {
3122           rect.top += 3;
3123           rect.bottom = rect.top + 3;
3124           rect.right -= 3;
3125           rect.left += 3;
3126         }
3127
3128       draw_3d_border (dc, &rect, FALSE);
3129       release_window_dc (&dc_info);
3130       return;
3131     }
3132
3133   if (!GTK_IS_PANED (widget))
3134     {
3135       gint xthick, ythick;
3136       GdkColor *light, *dark, *shadow;
3137       GdkRectangle dest;
3138
3139       gtk_paint_box (style, cr, state_type, shadow_type,
3140                      widget, detail, x, y, width, height);
3141
3142       light = &style->light[state_type];
3143       dark = &style->dark[state_type];
3144       shadow = &style->mid[state_type];
3145
3146       xthick = style->xthickness;
3147       ythick = style->ythickness;
3148
3149       dest.x = x + xthick;
3150       dest.y = y + ythick;
3151       dest.width = width - (xthick * 2);
3152       dest.height = height - (ythick * 2);
3153
3154       if (dest.width < dest.height)
3155         dest.x += 2;
3156       else
3157         dest.y += 2;
3158
3159       if (dest.width < dest.height)
3160         {
3161           _cairo_draw_line (cr, light, dest.x, dest.y, dest.x,
3162                          dest.height);
3163           _cairo_draw_line (cr, dark, dest.x + (dest.width / 2),
3164                          dest.y, dest.x + (dest.width / 2), dest.height);
3165           _cairo_draw_line (cr, shadow, dest.x + dest.width,
3166                          dest.y, dest.x + dest.width, dest.height);
3167         }
3168       else
3169         {
3170           _cairo_draw_line (cr, light, dest.x, dest.y,
3171                          dest.x + dest.width, dest.y);
3172           _cairo_draw_line (cr, dark, dest.x,
3173                          dest.y + (dest.height / 2),
3174                          dest.x + dest.width, dest.y + (dest.height / 2));
3175           _cairo_draw_line (cr, shadow, dest.x,
3176                          dest.y + dest.height, dest.x + dest.width,
3177                          dest.y + dest.height);
3178         }
3179     }
3180 }
3181
3182 static void
3183 draw_focus (GtkStyle *style,
3184             cairo_t *cr,
3185             GtkStateType state_type,
3186             GtkWidget *widget,
3187             const gchar *detail, gint x, gint y, gint width, gint height)
3188 {
3189   HDC dc;
3190   RECT rect;
3191   XpDCInfo dc_info;
3192
3193   if (!gtk_widget_get_can_focus (widget))
3194     {
3195       return;
3196     }
3197
3198   if (is_combo_box_child (widget)
3199       && (GTK_IS_ARROW (widget) || GTK_IS_BUTTON (widget)))
3200     {
3201       return;
3202     }
3203   if (GTK_IS_TREE_VIEW (gtk_widget_get_parent (widget)) /* list view bheader */)
3204     {
3205       return;
3206     }
3207
3208   dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
3209   DrawFocusRect (dc, &rect);
3210   release_window_dc (&dc_info);
3211 /*
3212     parent_class->draw_focus (style, cr, state_type,
3213                                                      widget, detail, x, y, width, height);
3214 */
3215 }
3216
3217 static void
3218 draw_layout (GtkStyle *style,
3219              cairo_t *cr,
3220              GtkStateType state_type,
3221              gboolean use_text,
3222              GtkWidget *widget,
3223              const gchar *detail,
3224              gint old_x, gint old_y, PangoLayout *layout)
3225 {
3226   GtkNotebook *notebook = NULL;
3227   gint x = old_x;
3228   gint y = old_y;
3229
3230   /* In the XP theme, labels don't appear correctly centered inside
3231    * notebook tabs, so we give them a gentle nudge two pixels to the
3232    * right.  A little hackish, but what are 'ya gonna do?  -- Cody
3233    */
3234   if (xp_theme_is_active () && detail && !strcmp (detail, "label"))
3235     {
3236       if (gtk_widget_get_parent (widget) != NULL)
3237         {
3238           if (GTK_IS_NOTEBOOK (gtk_widget_get_parent (widget)))
3239             {
3240               int side;
3241               notebook = GTK_NOTEBOOK (gtk_widget_get_parent (widget));
3242               side = gtk_notebook_get_tab_pos (notebook);
3243
3244               if (side == GTK_POS_TOP || side == GTK_POS_BOTTOM)
3245                 {
3246                   x += 2;
3247                 }
3248             }
3249         }
3250     }
3251
3252   parent_class->draw_layout (style, cr, state_type,
3253                              use_text, widget, detail, x, y, layout);
3254 }
3255
3256 static void
3257 msw_style_init_from_rc (GtkStyle *style, GtkRcStyle *rc_style)
3258 {
3259   setup_system_font (style);
3260   setup_menu_settings (gtk_settings_get_default ());
3261   setup_system_styles (style);
3262   parent_class->init_from_rc (style, rc_style);
3263 }
3264
3265 static void
3266 msw_style_class_init (MswStyleClass *klass)
3267 {
3268   GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
3269
3270   parent_class = g_type_class_peek_parent (klass);
3271
3272   style_class->init_from_rc = msw_style_init_from_rc;
3273   style_class->draw_arrow = draw_arrow;
3274   style_class->draw_box = draw_box;
3275   style_class->draw_check = draw_check;
3276   style_class->draw_option = draw_option;
3277   style_class->draw_tab = draw_tab;
3278   style_class->draw_flat_box = draw_flat_box;
3279   style_class->draw_expander = draw_expander;
3280   style_class->draw_extension = draw_extension;
3281   style_class->draw_box_gap = draw_box_gap;
3282   style_class->draw_shadow = draw_shadow;
3283   style_class->draw_hline = draw_hline;
3284   style_class->draw_vline = draw_vline;
3285   style_class->draw_handle = draw_handle;
3286   style_class->draw_resize_grip = draw_resize_grip;
3287   style_class->draw_slider = draw_slider;
3288   style_class->draw_focus = draw_focus;
3289   style_class->draw_layout = draw_layout;
3290 }
3291
3292 GType msw_type_style = 0;
3293
3294 void
3295 msw_style_register_type (GTypeModule *module)
3296 {
3297   const GTypeInfo object_info = {
3298     sizeof (MswStyleClass),
3299     (GBaseInitFunc) NULL,
3300     (GBaseFinalizeFunc) NULL,
3301     (GClassInitFunc) msw_style_class_init,
3302     NULL,                       /* class_finalize */
3303     NULL,                       /* class_data */
3304     sizeof (MswStyle),
3305     0,                          /* n_preallocs */
3306     (GInstanceInitFunc) NULL,
3307   };
3308
3309   msw_type_style = g_type_module_register_type (module,
3310                                                 GTK_TYPE_STYLE,
3311                                                 "MswStyle", &object_info, 0);
3312 }
3313
3314 void
3315 msw_style_init (void)
3316 {
3317   xp_theme_init ();
3318   msw_style_setup_system_settings ();
3319   setup_msw_rc_style ();
3320
3321   if (g_light_pen)
3322     {
3323       DeleteObject (g_light_pen);
3324       g_light_pen = NULL;
3325     }
3326
3327   if (g_dark_pen)
3328     {
3329       DeleteObject (g_dark_pen);
3330       g_dark_pen = NULL;
3331     }
3332 }
3333
3334 void
3335 msw_style_finalize (void)
3336 {
3337   if (g_dither_brush)
3338     {
3339       DeleteObject (g_dither_brush);
3340     }
3341
3342   if (g_light_pen)
3343     {
3344       DeleteObject (g_light_pen);
3345     }
3346
3347   if (g_dark_pen)
3348     {
3349       DeleteObject (g_dark_pen);
3350     }
3351 }