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