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