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