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