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