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