]> Pileus Git - ~andy/gtk/blob - modules/engines/ms-windows/msw_style.c
Add shadow-type style property, set shadow-type property of GtkEntry
[~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 ( xp_theme_is_active() ) {
1721         return xp_theme_draw( window, XP_THEME_ELEMENT_MENU_ITEM, style,
1722                               x, y, width, height, state_type, area );
1723     }
1724
1725     if( (parent = gtk_widget_get_parent(widget))
1726         &&  GTK_IS_MENU_BAR(parent) )
1727     {
1728         bar = GTK_MENU_SHELL(parent);
1729
1730         dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
1731         if( state_type == GTK_STATE_PRELIGHT ){
1732             draw_3d_border( dc, &rect, bar->active );
1733         }
1734         release_window_dc( style, window, state_type );
1735         return TRUE;
1736     }
1737     return FALSE;
1738 }
1739
1740 static HBRUSH
1741 get_dither_brush( void )
1742 {
1743     WORD pattern[8];
1744     HBITMAP pattern_bmp;
1745     int i;
1746
1747     if( g_dither_brush )
1748         return g_dither_brush;
1749     for ( i = 0; i < 8; i++ )
1750         pattern[i] = (WORD)(0x5555 << (i & 1));
1751     pattern_bmp = CreateBitmap(8, 8, 1, 1, &pattern);
1752     if (pattern_bmp) {
1753         g_dither_brush = CreatePatternBrush(pattern_bmp);
1754         DeleteObject(pattern_bmp);
1755     }
1756     return g_dither_brush;
1757 }
1758
1759 static gboolean 
1760 draw_tool_button(GdkWindow* window, GtkWidget* widget, GtkStyle* style, 
1761                  gint x, gint y, gint width, gint height, 
1762                  GtkStateType state_type, GdkRectangle* area )
1763 {
1764     HDC dc;
1765     RECT rect;
1766     gboolean is_toggled = FALSE;
1767
1768     if ( xp_theme_is_active() ) {
1769                 return (xp_theme_draw (window, XP_THEME_ELEMENT_TOOLBAR_BUTTON, style,
1770                                x, y, width, height, state_type, area) );
1771     }
1772
1773     if( GTK_IS_TOGGLE_BUTTON(widget) ){
1774         if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) ) {
1775             is_toggled = TRUE;
1776         }
1777     }
1778
1779     if( state_type != GTK_STATE_PRELIGHT
1780         && state_type != GTK_STATE_ACTIVE && !is_toggled )
1781         return FALSE;
1782
1783     dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
1784     if( state_type == GTK_STATE_PRELIGHT ){
1785         if( is_toggled ) {
1786             FillRect( dc, &rect, GetSysColorBrush(COLOR_BTNFACE));
1787         }
1788         draw_3d_border( dc, &rect, is_toggled);
1789     }
1790     else if ( state_type == GTK_STATE_ACTIVE ){
1791         if( is_toggled && ! is_menu_tool_button_child(widget->parent) ){
1792             SetTextColor( dc, GetSysColor(COLOR_3DHILIGHT) );
1793             SetBkColor( dc, GetSysColor(COLOR_BTNFACE) );
1794             FillRect( dc, &rect, get_dither_brush() );
1795         }
1796         draw_3d_border( dc, &rect, TRUE );
1797     }
1798     release_window_dc( style, window, state_type );
1799     return TRUE;
1800 }
1801
1802 static void
1803 draw_push_button( GdkWindow* window, GtkWidget* widget, GtkStyle* style, gint x, gint y,
1804                   gint width, gint height, 
1805                   GtkStateType state_type, gboolean is_default )
1806 {
1807         HDC dc;
1808         RECT rect;
1809
1810         dc = get_window_dc( style, window, state_type, 
1811                         x, y, width, height, &rect );
1812         if( GTK_IS_TOGGLE_BUTTON(widget) )  {
1813             if( state_type == GTK_STATE_PRELIGHT &&
1814                 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) )
1815             {
1816                 state_type = GTK_STATE_ACTIVE;
1817             }
1818         }
1819
1820         if( state_type == GTK_STATE_ACTIVE ) {
1821             if( GTK_IS_TOGGLE_BUTTON(widget) ) {
1822                 DrawEdge( dc, &rect, EDGE_SUNKEN, BF_RECT|BF_ADJUST);
1823                 SetTextColor( dc, GetSysColor(COLOR_3DHILIGHT) );
1824                 SetBkColor( dc, GetSysColor(COLOR_BTNFACE) );
1825                 FillRect( dc, &rect, get_dither_brush() );
1826             }
1827             else {
1828                 FrameRect( dc, &rect, GetSysColorBrush(COLOR_WINDOWFRAME) );
1829                 InflateRect( &rect, -1, -1 );
1830                 FrameRect( dc, &rect, GetSysColorBrush(COLOR_BTNSHADOW) );
1831                 InflateRect( &rect, -1, -1 );
1832                 FillRect( dc, &rect, GetSysColorBrush(COLOR_BTNFACE) );
1833             }
1834         }
1835         else {
1836                 if( is_default || GTK_WIDGET_HAS_FOCUS(widget) ) {
1837                     FrameRect( dc, &rect, GetSysColorBrush(COLOR_WINDOWFRAME) );
1838                     InflateRect( &rect, -1, -1 );
1839                 }
1840                 DrawFrameControl( dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH );
1841         }
1842         release_window_dc(style, window, state_type);
1843 }
1844
1845 static void
1846 draw_box (GtkStyle * style,
1847           GdkWindow * window,
1848           GtkStateType state_type,
1849           GtkShadowType shadow_type,
1850           GdkRectangle * area,
1851           GtkWidget * widget,
1852           const gchar * detail, gint x, gint y, gint width, gint height)
1853 {
1854     if (is_combo_box_child (widget) && detail && !strcmp (detail, "button")) {
1855         RECT rect;
1856         HDC dc;
1857         int cx;
1858            
1859         dc = get_window_dc (style, window, state_type, x, y, width - cx, height, &rect);
1860         FillRect (dc, &rect, GetSysColorBrush(COLOR_WINDOW));
1861         release_window_dc (style, window, state_type);
1862
1863         cx = 2 * GetSystemMetrics (SM_CXEDGE) + 16; /* TODO evaluate arrow width */
1864         x += width - cx;
1865         width = cx;
1866
1867         if (xp_theme_is_active () && xp_theme_draw (
1868             window, XP_THEME_ELEMENT_COMBOBUTTON, style,
1869             x, y, width, height, state_type, area))
1870             return;
1871     }
1872
1873     if (detail &&
1874         (!strcmp (detail, "button") || !strcmp (detail, "buttondefault")))
1875         {
1876             if (GTK_IS_TREE_VIEW (widget->parent)
1877                 || GTK_IS_CLIST (widget->parent))
1878                 {
1879                     if (xp_theme_draw
1880                         (window, XP_THEME_ELEMENT_LIST_HEADER, style, x, y,
1881                          width, height, state_type, area))
1882                         return;
1883                     else {
1884                         HDC dc;
1885                         RECT rect;
1886                         dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
1887
1888                         DrawFrameControl( dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH | 
1889                             (state_type == GTK_STATE_ACTIVE ? (DFCS_PUSHED|DFCS_FLAT) : 0 ) );
1890                         release_window_dc( style, window, state_type );
1891                 }
1892                 }
1893             else if (is_toolbar_child (widget->parent)
1894                     || (GTK_RELIEF_NONE == gtk_button_get_relief(GTK_BUTTON(widget)) ) )
1895                 {
1896                         if( draw_tool_button( window, widget, style, x, y, 
1897                                           width, height, state_type, area ) )
1898                 {
1899                         return;
1900                 }
1901                 }
1902             else
1903                 {
1904                         gboolean is_default = GTK_WIDGET_HAS_DEFAULT(widget);
1905                     if (xp_theme_draw
1906                         (window,
1907                          is_default ? XP_THEME_ELEMENT_DEFAULT_BUTTON :
1908                          XP_THEME_ELEMENT_BUTTON, style, x, y, width, height,
1909                          state_type, area))
1910                         {
1911                                 return;
1912                         }
1913                         draw_push_button( window, widget, style, 
1914                                 x, y, width, height, state_type, is_default );
1915                         return;
1916                 }
1917             return;
1918         }
1919     else if (detail && !strcmp (detail, "spinbutton"))
1920         {
1921             if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1922                 {
1923                     return;
1924                 }
1925         }
1926     else if (detail && (!strcmp (detail, "spinbutton_up")
1927                         || !strcmp (detail, "spinbutton_down")))
1928         {
1929             if ( ! xp_theme_draw ( window,
1930                                (!strcmp (detail, "spinbutton_up"))
1931                                ? XP_THEME_ELEMENT_SPIN_BUTTON_UP
1932                                : XP_THEME_ELEMENT_SPIN_BUTTON_DOWN,
1933                                style, x, y, width, height, state_type, area))
1934                 {
1935                 RECT rect;
1936                 HDC dc;
1937
1938                 dc = get_window_dc( style, window, state_type,
1939                                     x, y, width, height, &rect );
1940                 DrawEdge( dc, &rect, 
1941                         state_type == GTK_STATE_ACTIVE ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT );
1942                 release_window_dc( style, window, state_type );
1943                 }
1944             return;
1945         }
1946     else if (detail && !strcmp (detail, "slider"))
1947         {
1948             if (GTK_IS_SCROLLBAR (widget))
1949                 {
1950                     GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
1951                     gboolean is_v = GTK_IS_VSCROLLBAR (widget);
1952
1953                         if (xp_theme_draw (window,
1954                                        is_v
1955                                        ? XP_THEME_ELEMENT_SCROLLBAR_V
1956                                        : XP_THEME_ELEMENT_SCROLLBAR_H,
1957                                        style, x, y, width, height, state_type,
1958                                        area))
1959                         {
1960                             XpThemeElement gripper =
1961                                 (is_v ? XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V :
1962                                  XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H);
1963
1964                             /* Do not display grippers on tiny scroll bars,
1965                                the limit imposed is rather arbitrary, perhaps
1966                                we can fetch the gripper geometry from
1967                                somewhere and use that... */
1968                             if ((gripper ==
1969                                  XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H
1970                                  && width < 16)
1971                                 || (gripper ==
1972                                     XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V
1973                                     && height < 16))
1974                                 {
1975                                     return;
1976                                 }
1977
1978                             xp_theme_draw (window, gripper, style, x, y,
1979                                            width, height, state_type, area);
1980                             return;
1981                         }
1982                     else
1983                         {
1984                             if (scrollbar->range.adjustment->page_size >=
1985                                 (scrollbar->range.adjustment->upper -
1986                                  scrollbar->range.adjustment->lower))
1987                                 return;
1988                         }
1989                 }
1990         }
1991     else if (detail && !strcmp (detail, "bar"))
1992         {
1993             if (widget && GTK_IS_PROGRESS_BAR (widget))
1994                 {
1995                     GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
1996                     XpThemeElement xp_progress_bar =
1997                         map_gtk_progress_bar_to_xp (progress_bar, FALSE);
1998
1999                     if (xp_theme_draw (window, xp_progress_bar, style, x, y,
2000                                                            width, height, state_type, area))
2001                         {
2002                             return;
2003                         }
2004
2005                         shadow_type = GTK_SHADOW_NONE;
2006                 }
2007         }
2008     else if (detail && strcmp (detail, "menuitem") == 0)
2009         {
2010             shadow_type = GTK_SHADOW_NONE;
2011         if( draw_menu_item(window, widget, style, 
2012             x, y, width, height, state_type, area ) )
2013                 {
2014                     return;
2015                 }
2016         }
2017     else if (detail && !strcmp (detail, "trough"))
2018         {
2019             if (widget && GTK_IS_PROGRESS_BAR (widget))
2020                 {
2021                     GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
2022                     XpThemeElement xp_progress_bar =
2023                         map_gtk_progress_bar_to_xp (progress_bar, TRUE);
2024                     if (xp_theme_draw
2025                         (window, xp_progress_bar, style, x, y, width, height,
2026                          state_type, area))
2027                         {
2028                             return;
2029                         }
2030                     else
2031                         {
2032                             /* Blank in classic Windows */
2033                         }
2034                 }
2035             else if (widget && GTK_IS_SCROLLBAR (widget))
2036                 {
2037                     gboolean is_vertical = GTK_IS_VSCROLLBAR (widget);
2038
2039                     if (xp_theme_draw (window,
2040                                        is_vertical
2041                                        ? XP_THEME_ELEMENT_TROUGH_V
2042                                        : XP_THEME_ELEMENT_TROUGH_H,
2043                                        style,
2044                                        x, y, width, height, state_type, area))
2045                         {
2046                             return;
2047                         }
2048                     else
2049                         {
2050                             HDC dc;
2051                             RECT rect;
2052
2053                             sanitize_size (window, &width, &height);
2054                             dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
2055                             SetTextColor( dc, GetSysColor(COLOR_3DHILIGHT) );
2056                             SetBkColor( dc, GetSysColor(COLOR_BTNFACE) );
2057                             FillRect( dc, &rect, get_dither_brush() );
2058                             release_window_dc( style, window, state_type );
2059
2060                             return;
2061                         }
2062                 }
2063             else if (widget && GTK_IS_SCALE (widget))
2064                 {
2065                     gboolean is_vertical = GTK_IS_VSCALE (widget);
2066
2067                     if (!xp_theme_is_active ())
2068                         {
2069                             parent_class->draw_box (style, window, state_type,
2070                                                     GTK_SHADOW_NONE, area,
2071                                                     widget, detail, x, y,
2072                                                     width, height);
2073                         }
2074
2075                     if (is_vertical)
2076                         {
2077                             if (xp_theme_draw
2078                                 (window, XP_THEME_ELEMENT_SCALE_TROUGH_V,
2079                                  style, (2 * x + width) / 2, y, 2, height,
2080                                  state_type, area))
2081                                 return;
2082
2083                             parent_class->draw_box (style, window, state_type,
2084                                                     GTK_SHADOW_ETCHED_IN,
2085                                                     area, NULL, NULL,
2086                                                     (2 * x + width) / 2, y, 1,
2087                                                     height);
2088                         }
2089                     else
2090                         {
2091                             if (xp_theme_draw
2092                                 (window, XP_THEME_ELEMENT_SCALE_TROUGH_H,
2093                                  style, x, (2 * y + height) / 2, width, 2,
2094                                  state_type, area))
2095                                 return;
2096
2097                             parent_class->draw_box (style, window, state_type,
2098                                                     GTK_SHADOW_ETCHED_IN,
2099                                                     area, NULL, NULL, x,
2100                                                     (2 * y + height) / 2,
2101                                                     width, 1);
2102                         }
2103                     return;
2104                 }
2105         }
2106     else if (detail && strcmp (detail, "optionmenu") == 0)
2107         {
2108             if (xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT,
2109                                style, x, y, width, height, state_type, area))
2110                 {
2111                     return;
2112                 }
2113         }
2114     else if (detail
2115              && (strcmp (detail, "vscrollbar") == 0
2116                  || strcmp (detail, "hscrollbar") == 0))
2117         {
2118             return;
2119         }
2120     else if (detail
2121              && (strcmp (detail, "handlebox_bin") == 0
2122                  || strcmp (detail, "toolbar") == 0
2123                  || strcmp (detail, "menubar") == 0))
2124         {
2125             sanitize_size( window, &width, &height );
2126             if (xp_theme_draw (window, XP_THEME_ELEMENT_REBAR,
2127                                style, x, y, width, height, state_type, area))
2128                 {
2129                     return;
2130                 }
2131         }
2132     else if (detail && (!strcmp (detail, "handlebox"))) /* grip */
2133         {
2134             if( !xp_theme_is_active() ) {
2135                 return;
2136             }
2137         }
2138     else
2139         {
2140             const gchar *name = gtk_widget_get_name (widget);
2141
2142             if (name && !strcmp (name, "gtk-tooltips"))
2143                 {
2144                     if (xp_theme_draw
2145                         (window, XP_THEME_ELEMENT_TOOLTIP, style, x, y, width,
2146                          height, state_type, area))
2147                         {
2148                             return;
2149                         }
2150                     else
2151                         {
2152                             HBRUSH brush;
2153                             RECT rect;
2154                             HDC hdc;
2155
2156                                 hdc = get_window_dc(style, window, state_type, x, y, width, height, &rect);
2157
2158                             brush = GetSysColorBrush (COLOR_3DDKSHADOW);
2159                             if (brush)
2160                                 FrameRect (hdc, &rect, brush);
2161                             InflateRect (&rect, -1, -1);
2162                             FillRect (hdc, &rect,
2163                                       (HBRUSH) (COLOR_INFOBK + 1));
2164
2165                                 release_window_dc (style, window, state_type);
2166
2167                             return;
2168                         }
2169
2170                 }
2171         }
2172
2173     parent_class->draw_box (style, window, state_type, shadow_type, area,
2174                             widget, detail, x, y, width, height);
2175
2176     if (detail && strcmp (detail, "optionmenu") == 0)
2177         {
2178             GtkRequisition indicator_size;
2179             GtkBorder indicator_spacing;
2180             gint vline_x;
2181
2182             option_menu_get_props (widget, &indicator_size,
2183                                    &indicator_spacing);
2184
2185             sanitize_size (window, &width, &height);
2186
2187             if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
2188                 vline_x =
2189                     x + indicator_size.width + indicator_spacing.left +
2190                     indicator_spacing.right;
2191             else
2192                 vline_x =
2193                     x + width - (indicator_size.width +
2194                                  indicator_spacing.left +
2195                                  indicator_spacing.right) - style->xthickness;
2196
2197             parent_class->draw_vline (style, window, state_type, area, widget,
2198                                       detail,
2199                                       y + style->ythickness + 1,
2200                                       y + height - style->ythickness - 3,
2201                                       vline_x);
2202         }
2203 }
2204
2205 static void
2206 draw_tab (GtkStyle * style,
2207           GdkWindow * window,
2208           GtkStateType state,
2209           GtkShadowType shadow,
2210           GdkRectangle * area,
2211           GtkWidget * widget,
2212           const gchar * detail, gint x, gint y, gint width, gint height)
2213 {
2214     GtkRequisition indicator_size;
2215     GtkBorder indicator_spacing;
2216
2217     gint arrow_height;
2218
2219     g_return_if_fail (style != NULL);
2220     g_return_if_fail (window != NULL);
2221
2222     if (detail && !strcmp (detail, "optionmenutab"))
2223         {
2224             if (xp_theme_draw (window, XP_THEME_ELEMENT_COMBOBUTTON,
2225                                style, x - 5, widget->allocation.y + 1,
2226                                width + 10, widget->allocation.height - 2,
2227                                state, area))
2228                 {
2229                     return;
2230                 }
2231         }
2232
2233     if (widget)
2234         gtk_widget_style_get (widget, "indicator_size", &indicator_size,
2235                               NULL);
2236
2237     option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2238
2239     x += (width - indicator_size.width) / 2;
2240     arrow_height = (indicator_size.width + 1) / 2;
2241
2242     y += (height - arrow_height) / 2;
2243
2244     draw_varrow (window, style->black_gc, shadow, area, GTK_ARROW_DOWN,
2245                  x, y, indicator_size.width, arrow_height);
2246 }
2247
2248 /* Draw classic Windows tab - thanks Mozilla!
2249   (no system API for this, but DrawEdge can draw all the parts of a tab) */
2250 static void DrawTab(HDC hdc, const RECT R, gint32 aPosition, gboolean aSelected,
2251                      gboolean aDrawLeft, gboolean aDrawRight)
2252  {
2253    gint32 leftFlag, topFlag, rightFlag, lightFlag, shadeFlag;
2254    RECT topRect, sideRect, bottomRect, lightRect, shadeRect;
2255    gint32 selectedOffset, lOffset, rOffset;
2256
2257    selectedOffset = aSelected ? 1 : 0;
2258    lOffset = aDrawLeft ? 2 : 0;
2259    rOffset = aDrawRight ? 2 : 0;
2260
2261    /* Get info for tab orientation/position (Left, Top, Right, Bottom) */
2262    switch (aPosition) {
2263      case BF_LEFT:
2264        leftFlag = BF_TOP; topFlag = BF_LEFT;
2265        rightFlag = BF_BOTTOM;
2266        lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
2267        shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
2268
2269       SetRect(&topRect, R.left, R.top+lOffset, R.right, R.bottom-rOffset);
2270       SetRect(&sideRect, R.left+2, R.top, R.right-2+selectedOffset, R.bottom);
2271       SetRect(&bottomRect, R.right-2, R.top, R.right, R.bottom);
2272       SetRect(&lightRect, R.left, R.top, R.left+3, R.top+3);
2273       SetRect(&shadeRect, R.left+1, R.bottom-2, R.left+2, R.bottom-1);
2274       break;
2275     case BF_TOP:
2276        leftFlag = BF_LEFT; topFlag = BF_TOP;
2277        rightFlag = BF_RIGHT;
2278        lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
2279        shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
2280
2281        SetRect(&topRect, R.left+lOffset, R.top, R.right-rOffset, R.bottom);
2282        SetRect(&sideRect, R.left, R.top+2, R.right, R.bottom-1+selectedOffset);
2283        SetRect(&bottomRect, R.left, R.bottom-1, R.right, R.bottom);
2284        SetRect(&lightRect, R.left, R.top, R.left+3, R.top+3);
2285        SetRect(&shadeRect, R.right-2, R.top+1, R.right-1, R.top+2);
2286        break;
2287      case BF_RIGHT:
2288        leftFlag = BF_TOP; topFlag = BF_RIGHT;
2289        rightFlag = BF_BOTTOM;
2290        lightFlag = BF_DIAGONAL_ENDTOPLEFT;
2291        shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
2292
2293        SetRect(&topRect, R.left, R.top+lOffset, R.right, R.bottom-rOffset);
2294        SetRect(&sideRect, R.left+2-selectedOffset, R.top, R.right-2, R.bottom);
2295        SetRect(&bottomRect, R.left, R.top, R.left+2, R.bottom);
2296        SetRect(&lightRect, R.right-3, R.top, R.right-1, R.top+2);
2297        SetRect(&shadeRect, R.right-2, R.bottom-3, R.right, R.bottom-1);
2298        break;
2299      case BF_BOTTOM:
2300        leftFlag = BF_LEFT; topFlag = BF_BOTTOM;
2301        rightFlag = BF_RIGHT;
2302        lightFlag = BF_DIAGONAL_ENDTOPLEFT;
2303        shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
2304
2305        SetRect(&topRect, R.left+lOffset, R.top, R.right-rOffset, R.bottom);
2306        SetRect(&sideRect, R.left, R.top+2-selectedOffset, R.right, R.bottom-2);
2307        SetRect(&bottomRect, R.left, R.top, R.right, R.top+2);
2308        SetRect(&lightRect, R.left, R.bottom-3, R.left+2, R.bottom-1);
2309        SetRect(&shadeRect, R.right-2, R.bottom-3, R.right, R.bottom-1);
2310        break;
2311      default:
2312        g_return_if_reached();
2313    }
2314
2315    /* Background */
2316    FillRect(hdc, &R, (HBRUSH) (COLOR_3DFACE+1) );
2317
2318    /* Tab "Top" */
2319    DrawEdge(hdc, &topRect, EDGE_RAISED, BF_SOFT | topFlag);
2320
2321    /* Tab "Bottom" */
2322    if (!aSelected)
2323      DrawEdge(hdc, &bottomRect, EDGE_RAISED, BF_SOFT | topFlag);
2324
2325    /* Tab "Sides" */
2326    if (!aDrawLeft)
2327      leftFlag = 0;
2328    if (!aDrawRight)
2329      rightFlag = 0;
2330    DrawEdge(hdc, &sideRect, EDGE_RAISED, BF_SOFT | leftFlag | rightFlag);
2331
2332    /* Tab Diagonal Corners */
2333    if (aDrawLeft)
2334      DrawEdge(hdc, &lightRect, EDGE_RAISED, BF_SOFT | lightFlag);
2335
2336    if (aDrawRight)
2337      DrawEdge(hdc, &shadeRect, EDGE_RAISED, BF_SOFT | shadeFlag);
2338  }
2339
2340 static void
2341 draw_extension (GtkStyle * style,
2342                 GdkWindow * window,
2343                 GtkStateType state_type,
2344                 GtkShadowType shadow_type,
2345                 GdkRectangle * area,
2346                 GtkWidget * widget,
2347                 const gchar * detail,
2348                 gint x,
2349                 gint y, gint width, gint height, GtkPositionType gap_side)
2350 {
2351     if (widget && GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "tab"))
2352         {
2353             GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2354             GdkPixmap *pixmap = NULL;
2355             GdkDrawable *target = NULL;
2356             gint x2 = 0, y2 = 0, w2 = width, h2 = height;
2357             int tab_part = XP_THEME_ELEMENT_TAB_ITEM;
2358             int real_gap_side = gtk_notebook_get_tab_pos (notebook);
2359             int border_width = gtk_container_get_border_width (GTK_CONTAINER (notebook));
2360
2361             /* why this differs from the above gap_side, i have no idea... */
2362             if (real_gap_side == GTK_POS_LEFT)
2363               {
2364                 /* Create "rotated" pixmap.. swap width and height */
2365                 pixmap = gdk_pixmap_new (window, height, width, -1);
2366                 target = pixmap;
2367                 x2 = 0;
2368                 y2 = 0;
2369                 w2 = height;
2370                 h2 = width - (state_type == GTK_STATE_NORMAL ? 0 : notebook->tab_hborder);
2371
2372                 /* If we are currently rendering the bottom-most tab, and if that tab is the selected tab... */
2373                 if (widget->allocation.y + widget->allocation.height - border_width == y + height &&
2374                     state_type == GTK_STATE_NORMAL)
2375                   {
2376                     w2--;
2377                   }
2378               }
2379             else if (real_gap_side == GTK_POS_RIGHT)
2380               {
2381                 /* Create "rotated" pixmap.. swap width and height */
2382                 x2 = 0;
2383                 y2 = 0;
2384                 w2 = height;
2385                 h2 = width - (state_type == GTK_STATE_NORMAL ? 0 : notebook->tab_hborder);
2386                 pixmap = gdk_pixmap_new (window, w2, h2, -1);
2387                 target = pixmap;
2388
2389                 /* If we are currently rendering the bottom-most tab, and if that tab is the selected tab... */
2390                 if (widget->allocation.y + widget->allocation.height - border_width == y + height &&
2391                     state_type == GTK_STATE_NORMAL)
2392                   {
2393                     w2--;
2394                   }
2395               }
2396             else if (real_gap_side == GTK_POS_TOP)
2397               {
2398                 target = window;
2399                 x2 = x;
2400                 y2 = y;
2401                 w2 = width;
2402                 if (state_type == GTK_STATE_NORMAL)
2403                   h2 = height;
2404                 else
2405                   h2 = height - notebook->tab_vborder;
2406
2407                 /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */
2408                 if (widget->allocation.x + widget->allocation.width - border_width == x + width &&
2409                     state_type == GTK_STATE_NORMAL)
2410                   {
2411                     x2--;
2412                   }
2413               }
2414             else if (real_gap_side == GTK_POS_BOTTOM)
2415               {
2416                 x2 = x;
2417                 y2 = y + (state_type == GTK_STATE_NORMAL ? 0 : notebook->tab_vborder);
2418                 w2 = width;
2419                 h2 = height - (state_type == GTK_STATE_NORMAL ? 0 : notebook->tab_vborder * 2);
2420                 target = window;
2421
2422                 /* If we are currently drawing the right-most tab (any state)... */
2423                 if (widget->allocation.x + widget->allocation.width - border_width == x + width)
2424                   {
2425                     x2--;
2426                     w2--;
2427                   }
2428               }
2429
2430             if (xp_theme_draw (target, tab_part, style, x2, y2, w2, h2, state_type, NULL /*area*/))
2431                 {
2432                     GdkPixbufRotation rotation = GDK_PIXBUF_ROTATE_NONE;
2433                     if (real_gap_side == GTK_POS_BOTTOM)
2434                         rotation = GDK_PIXBUF_ROTATE_UPSIDEDOWN;
2435                     else if (real_gap_side == GTK_POS_LEFT)
2436                         rotation = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
2437                     else if (real_gap_side == GTK_POS_RIGHT)
2438                         rotation = GDK_PIXBUF_ROTATE_CLOCKWISE;
2439
2440                     if (rotation != GDK_PIXBUF_ROTATE_NONE)
2441                         {
2442                            GdkPixbuf * pixbuf, * rotated;
2443
2444                            pixbuf = gdk_pixbuf_get_from_drawable (NULL, target, NULL, x2, y2, 0, 0, w2, h2);
2445
2446                            rotated = gdk_pixbuf_rotate_simple (pixbuf, rotation);
2447                            g_object_unref (pixbuf);
2448                            pixbuf = rotated;
2449
2450                            if (real_gap_side == GTK_POS_RIGHT)
2451                              {
2452                                x2 = x + (state_type == GTK_STATE_NORMAL ? 0 : notebook->tab_hborder);
2453                                y2 = y;
2454                                w2 = width - (state_type == GTK_STATE_NORMAL ? 0 : notebook->tab_hborder);
2455                                h2 = height;
2456
2457                                if (widget->allocation.y + widget->allocation.height - border_width == y + height &&
2458                                    state_type == GTK_STATE_NORMAL)
2459                                  {
2460                                    h2--;
2461                                  }
2462                              }
2463                            else if (real_gap_side == GTK_POS_LEFT)
2464                              {
2465                                x2 = x;
2466                                y2 = y;
2467                                w2 = width - (state_type == GTK_STATE_NORMAL ? 0 : notebook->tab_hborder);
2468                                h2 = height;
2469
2470                                if (widget->allocation.y + widget->allocation.height - border_width == y + height &&
2471                                    state_type == GTK_STATE_NORMAL)
2472                                  {
2473                                    h2--;
2474                                  }
2475                              }
2476
2477                            gdk_draw_pixbuf (window, NULL, pixbuf, 0, 0, x2, y2, w2, h2, GDK_RGB_DITHER_NONE, 0, 0);
2478
2479                            g_object_unref (G_OBJECT (pixbuf));
2480
2481                            if (real_gap_side == GTK_POS_LEFT || real_gap_side == GTK_POS_RIGHT)
2482                              {
2483                                g_object_unref (pixmap);
2484                              }
2485                         }
2486                     return;
2487                 } else if (real_gap_side == GTK_POS_TOP || real_gap_side == GTK_POS_BOTTOM) {
2488                     /* experimental tab-drawing code from mozilla */
2489                     RECT rect;
2490                     HDC dc;
2491                     gint32 aPosition;
2492
2493                     dc = get_window_dc(style, window, state_type, x, y, width, height, &rect);
2494
2495                     if (real_gap_side == GTK_POS_TOP)
2496                         aPosition = BF_TOP;
2497                     else if (real_gap_side == GTK_POS_BOTTOM)
2498                         aPosition = BF_BOTTOM;
2499                     else if (real_gap_side == GTK_POS_LEFT)
2500                         aPosition = BF_LEFT;
2501                     else
2502                         aPosition = BF_RIGHT;
2503
2504                     if( state_type == GTK_STATE_PRELIGHT )
2505                         state_type = GTK_STATE_NORMAL;
2506                     if (area)
2507                         gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2508                     DrawTab (dc, rect, aPosition, state_type != GTK_STATE_PRELIGHT, (real_gap_side != GTK_POS_LEFT), (real_gap_side != GTK_POS_RIGHT));
2509                     if (area)
2510                         gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2511
2512                     release_window_dc (style, window, state_type);
2513                     return;
2514                 }
2515         }
2516     parent_class->draw_extension
2517         (style, window, state_type, shadow_type, area, widget, detail,
2518          x, y, width, height, gap_side);
2519 }
2520
2521 static void
2522 draw_box_gap (GtkStyle * style, GdkWindow * window, GtkStateType state_type,
2523               GtkShadowType shadow_type, GdkRectangle * area,
2524               GtkWidget * widget, const gchar * detail, gint x,
2525               gint y, gint width, gint height, GtkPositionType gap_side,
2526               gint gap_x, gint gap_width)
2527 {
2528     if (GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "notebook"))
2529         {
2530             GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2531             int side = gtk_notebook_get_tab_pos (notebook);
2532             int x2 = x, y2 = y, w2 = width, h2 = height;
2533
2534             if (side == GTK_POS_TOP)
2535               {
2536                 x2 = x;
2537                 y2 = y - notebook->tab_vborder;
2538                 w2 = width;
2539                 h2 = height + notebook->tab_vborder * 2;
2540               }
2541             else if (side == GTK_POS_BOTTOM)
2542               {
2543                 x2 = x;
2544                 y2 = y;
2545                 w2 = width;
2546                 h2 = height + notebook->tab_vborder * 2;
2547               }
2548             else if (side == GTK_POS_LEFT)
2549               {
2550                 x2 = x - notebook->tab_hborder;
2551                 y2 = y;
2552                 w2 = width + notebook->tab_hborder;
2553                 h2 = height;
2554               }
2555             else if (side == GTK_POS_RIGHT)
2556               {
2557                 x2 = x;
2558                 y2 = y;
2559                 w2 = width + notebook->tab_hborder * 2;
2560                 h2 = height;
2561               }
2562
2563             if (xp_theme_draw (window, XP_THEME_ELEMENT_TAB_PANE, style,
2564                                x2, y2, w2, h2, state_type, area))
2565                 {
2566                     return;
2567                 }
2568         }
2569
2570     parent_class->draw_box_gap (style, window, state_type, shadow_type,
2571                                 area, widget, detail, x, y, width, height,
2572                                 gap_side, gap_x, gap_width);
2573 }
2574
2575 static gboolean is_popup_window_child( GtkWidget* widget )
2576 {
2577     GtkWidget* top;
2578     GtkWindowType type = -1;
2579
2580     top = gtk_widget_get_toplevel( widget );
2581     if( top && GTK_IS_WINDOW(top) ) {
2582         g_object_get(top, "type", &type, NULL );
2583         if( type == GTK_WINDOW_POPUP ) { /* Hack for combo boxes */
2584             return TRUE;
2585         }
2586     }
2587     return FALSE;
2588 }
2589
2590 static void
2591 draw_flat_box (GtkStyle * style, GdkWindow * window,
2592                GtkStateType state_type, GtkShadowType shadow_type,
2593                GdkRectangle * area, GtkWidget * widget,
2594                const gchar * detail, gint x, gint y, gint width, gint height)
2595 {
2596     if( detail ) {
2597         if ( !strcmp (detail, "checkbutton") )
2598         {
2599             if (state_type == GTK_STATE_PRELIGHT)
2600                 {
2601                     return;
2602                 }
2603         }
2604     }
2605
2606     parent_class->draw_flat_box (style, window, state_type, shadow_type,
2607                                  area, widget, detail, x, y, width, height);
2608 }
2609
2610 static gboolean
2611 draw_menu_border ( GdkWindow* win, GtkStyle* style, 
2612                                   gint x, gint y, gint width, gint height )
2613 {
2614     RECT rect;
2615     HDC dc;
2616
2617     dc = get_window_dc (style, win, GTK_STATE_NORMAL, x, y, width, height, &rect );
2618     if (!dc)
2619         return FALSE;
2620     if( xp_theme_is_active() ) {
2621         FrameRect( dc, &rect, GetSysColorBrush(COLOR_3DSHADOW) );
2622     }
2623     else {
2624         DrawEdge( dc, &rect, EDGE_RAISED, BF_RECT );
2625     }
2626     release_window_dc( style, win, GTK_STATE_NORMAL );
2627     return TRUE;
2628 }
2629
2630 static void
2631 draw_shadow (GtkStyle * style,
2632              GdkWindow * window,
2633              GtkStateType state_type,
2634              GtkShadowType shadow_type,
2635              GdkRectangle * area,
2636              GtkWidget * widget,
2637              const gchar * detail, gint x, gint y, gint width, gint height)
2638 {
2639     gboolean is_handlebox;
2640     gboolean is_toolbar;
2641
2642     if( detail && !strcmp( detail, "frame") )
2643         {
2644         HDC dc;
2645         RECT rect;
2646         dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
2647         if( is_popup_window_child(widget) ) {
2648             FrameRect( dc, &rect, GetSysColorBrush( COLOR_WINDOWFRAME ) );
2649         }
2650         else{
2651             switch( shadow_type ){
2652             case GTK_SHADOW_IN:
2653                 draw_3d_border(dc, &rect, TRUE);
2654                 break;
2655             case GTK_SHADOW_OUT:
2656                 draw_3d_border(dc, &rect, FALSE);
2657                 break;
2658             case GTK_SHADOW_ETCHED_IN:
2659                 draw_3d_border(dc, &rect, TRUE);
2660                 InflateRect( &rect, -1, -1 );
2661                 draw_3d_border(dc, &rect, FALSE);
2662                 break;
2663             case GTK_SHADOW_ETCHED_OUT:
2664                 draw_3d_border(dc, &rect, FALSE);
2665                 InflateRect( &rect, -1, -1 );
2666                 draw_3d_border(dc, &rect, TRUE);
2667                 break;
2668             case GTK_SHADOW_NONE:
2669                 break;
2670             }
2671         }
2672         release_window_dc( style, window, state_type );
2673         return;
2674     }
2675     if (detail && (!strcmp (detail, "entry") || !strcmp (detail, "combobox")) )
2676         {
2677             if( shadow_type != GTK_SHADOW_IN )
2678                 return;
2679
2680             if ( !xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT, style,
2681                                  x, y, width, height, state_type, area))
2682             {
2683                 HDC dc;
2684                 RECT rect;
2685
2686                 dc = get_window_dc (style, window, state_type, 
2687                                     x, y, width, height, &rect);
2688                 DrawEdge (dc, &rect, EDGE_SUNKEN, BF_RECT);
2689                 release_window_dc (style, window, state_type);
2690             }
2691
2692             return;
2693         }
2694
2695     if( detail && !strcmp( detail, "spinbutton" ) )
2696                 {
2697         return;
2698     }
2699
2700     if (detail && !strcmp (detail, "menu"))
2701                         {
2702             if ( draw_menu_border ( window, style, x, y, width, height ) ) {
2703                     return;
2704                         }
2705                 }
2706
2707     if (detail && !strcmp (detail, "handlebox"))
2708         return;
2709
2710     is_handlebox = (detail && !strcmp (detail, "handlebox_bin"));
2711     is_toolbar = (detail && (!strcmp (detail, "toolbar") || !strcmp(detail, "menubar")));
2712
2713     if ( is_toolbar || is_handlebox )
2714                                 {
2715         if( widget ) {
2716             HDC dc;
2717             RECT rect;
2718             HGDIOBJ old_pen = NULL;
2719             GtkPositionType pos;
2720
2721             sanitize_size (window, &width, &height);
2722
2723             if( is_handlebox ) {
2724                 pos = gtk_handle_box_get_handle_position(GTK_HANDLE_BOX(widget));
2725                 /*
2726                     If the handle box is at left side, 
2727                     we shouldn't draw its right border.
2728                     The same holds true for top, right, and bottom.
2729                 */
2730                 switch( pos ) {
2731                 case GTK_POS_LEFT:
2732                     pos = GTK_POS_RIGHT;    break;
2733                 case GTK_POS_RIGHT:
2734                     pos = GTK_POS_LEFT;     break;
2735                 case GTK_POS_TOP:
2736                     pos = GTK_POS_BOTTOM;   break;
2737                 case GTK_POS_BOTTOM:
2738                     pos = GTK_POS_TOP;      break;
2739                                 }
2740                         }
2741             else {
2742                 GtkWidget* parent = gtk_widget_get_parent(widget);
2743                 /* Dirty hack for toolbars contained in handle boxes */
2744                 if( GTK_IS_HANDLE_BOX( parent ) ) {
2745                     pos = gtk_handle_box_get_handle_position( GTK_HANDLE_BOX( parent ) );
2746                         }
2747                 else {
2748                     /*
2749                         Dirty hack:
2750                         Make pos != all legal enum vaules of GtkPositionType.
2751                         So every border will be draw.
2752                     */
2753                     pos = (GtkPositionType)-1;
2754                 }
2755                                 }
2756
2757             dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
2758             if( pos != GTK_POS_LEFT ) {
2759                 old_pen = SelectObject( dc, get_light_pen() );
2760                 MoveToEx( dc, rect.left, rect.top, NULL );
2761                 LineTo( dc, rect.left, rect.bottom );
2762                                 }
2763             if( pos != GTK_POS_TOP ) {
2764                 old_pen = SelectObject( dc, get_light_pen() );
2765                 MoveToEx( dc, rect.left, rect.top, NULL );
2766                 LineTo( dc, rect.right, rect.top );
2767                         }
2768             if( pos != GTK_POS_RIGHT ) {
2769                 old_pen = SelectObject( dc, get_dark_pen() );
2770                 MoveToEx( dc, rect.right-1, rect.top, NULL );
2771                 LineTo( dc, rect.right-1, rect.bottom );
2772                         }
2773             if( pos != GTK_POS_BOTTOM ) {
2774                 old_pen = SelectObject( dc, get_dark_pen() );
2775                 MoveToEx( dc, rect.left, rect.bottom-1, NULL );
2776                 LineTo( dc, rect.right, rect.bottom-1 );
2777                 }
2778             if (old_pen)
2779                 SelectObject( dc, old_pen );
2780             release_window_dc( style, window, state_type );
2781                         }
2782         return;
2783                 }
2784
2785     if (detail && !strcmp (detail, "statusbar")) {
2786             return;
2787         }
2788
2789     parent_class->draw_shadow (style, window, state_type, shadow_type, area,
2790                                widget, detail, x, y, width, height);
2791 }
2792
2793 static void
2794 draw_hline (GtkStyle * style,
2795             GdkWindow * window,
2796             GtkStateType state_type,
2797             GdkRectangle * area,
2798             GtkWidget * widget,
2799             const gchar * detail, gint x1, gint x2, gint y)
2800 {
2801   if (xp_theme_is_active () && detail && !strcmp(detail, "menuitem")) {
2802         if(xp_theme_draw (window, XP_THEME_ELEMENT_MENU_SEPARATOR, style, x1, y, x2, 1, state_type, area))
2803                 return;
2804         else {
2805             if (area)
2806               gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2807
2808             gdk_draw_line (window, style->dark_gc[state_type], x1, y, x2, y);
2809
2810             if (area)
2811               gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2812         }
2813   } else {
2814       if( style->ythickness == 2 )
2815       {
2816         if (area)
2817         {
2818           gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2819           gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
2820         }
2821         gdk_draw_line (window, style->dark_gc[state_type], x1, y, x2, y);
2822         ++y;
2823         gdk_draw_line (window, style->light_gc[state_type], x1, y, x2, y);
2824         if (area)
2825         {
2826           gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2827           gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
2828         }
2829       }
2830       else
2831       {
2832     parent_class->draw_hline (style, window, state_type, area, widget,
2833                               detail, x1, x2, y);
2834   }
2835   }
2836 }
2837
2838 static void
2839 draw_vline (GtkStyle * style,
2840             GdkWindow * window,
2841             GtkStateType state_type,
2842             GdkRectangle * area,
2843             GtkWidget * widget,
2844             const gchar * detail, gint y1, gint y2, gint x)
2845 {
2846   if( style->xthickness == 2 )
2847   {
2848     if (area)
2849     {
2850       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2851       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
2852     }
2853     gdk_draw_line (window, style->dark_gc[state_type], x, y1, x, y2);
2854     ++x;
2855     gdk_draw_line (window, style->light_gc[state_type], x, y1, x, y2);
2856     if (area)
2857     {
2858       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2859       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
2860     }
2861   }
2862   else
2863   {
2864     parent_class->draw_vline (style, window, state_type, area, widget,
2865                               detail, y1, y2, x);
2866   }
2867 }
2868
2869 static void
2870 draw_slider (GtkStyle * style,
2871              GdkWindow * window,
2872              GtkStateType state_type,
2873              GtkShadowType shadow_type,
2874              GdkRectangle * area,
2875              GtkWidget * widget,
2876              const gchar * detail,
2877              gint x,
2878              gint y, gint width, gint height, GtkOrientation orientation)
2879 {
2880     if (GTK_IS_SCALE (widget) &&
2881         xp_theme_draw (window,
2882                        ((orientation ==
2883                          GTK_ORIENTATION_VERTICAL) ?
2884                         XP_THEME_ELEMENT_SCALE_SLIDER_V :
2885                         XP_THEME_ELEMENT_SCALE_SLIDER_H), style, x, y, width,
2886                        height, state_type, area))
2887         {
2888             return;
2889         }
2890
2891     parent_class->draw_slider (style, window, state_type, shadow_type, area,
2892                                widget, detail, x, y, width, height,
2893                                orientation);
2894 }
2895
2896 static void
2897 draw_resize_grip (GtkStyle * style,
2898                   GdkWindow * window,
2899                   GtkStateType state_type,
2900                   GdkRectangle * area,
2901                   GtkWidget * widget,
2902                   const gchar * detail,
2903                   GdkWindowEdge edge, gint x, gint y, gint width, gint height)
2904 {
2905     if (detail && !strcmp (detail, "statusbar"))
2906         {
2907             if (xp_theme_draw
2908                 (window, XP_THEME_ELEMENT_STATUS_GRIPPER, style, x, y, width,
2909                  height, state_type, area))
2910                         return;
2911                 else {
2912                         RECT rect;
2913                         HDC dc = get_window_dc(style, window, state_type, x, y, width, height, &rect);
2914
2915                         if (area)
2916                                 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2917                         DrawFrameControl(dc, &rect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
2918                         release_window_dc(style, window, state_type);
2919                         if (area)
2920                                 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2921                         return;
2922                 }
2923         }
2924
2925     parent_class->draw_resize_grip (style, window, state_type, area,
2926                                     widget, detail, edge, x, y, width,
2927                                     height);
2928 }
2929
2930 static void
2931 draw_handle (GtkStyle * style,
2932              GdkWindow * window,
2933              GtkStateType state_type,
2934              GtkShadowType shadow_type,
2935              GdkRectangle * area,
2936              GtkWidget * widget,
2937              const gchar * detail,
2938              gint x,
2939              gint y, gint width, gint height, GtkOrientation orientation)
2940 {
2941     HDC dc;
2942     RECT rect;
2943
2944     if (is_toolbar_child (widget))
2945         {
2946             XpThemeElement hndl;
2947
2948             sanitize_size (window, &width, &height);
2949
2950             if( GTK_IS_HANDLE_BOX(widget) ) {
2951                 GtkPositionType pos;
2952                 pos = gtk_handle_box_get_handle_position(GTK_HANDLE_BOX(widget));
2953                 if( pos == GTK_POS_TOP || pos == GTK_POS_BOTTOM ) {
2954                     orientation = GTK_ORIENTATION_HORIZONTAL;
2955                 }
2956                 else {
2957                     orientation = GTK_ORIENTATION_VERTICAL;
2958                 }
2959             }
2960
2961             if ( orientation == GTK_ORIENTATION_VERTICAL )
2962                 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_V;
2963             else
2964                 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_H;
2965
2966             if (xp_theme_draw (window, hndl, style, x, y, width, height,
2967                                state_type, area))
2968                 {
2969                     return;
2970                 }
2971
2972             dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
2973             if ( orientation == GTK_ORIENTATION_VERTICAL ) {
2974                 rect.left += 3;
2975                 rect.right = rect.left + 3;
2976                 rect.bottom -= 3;
2977                 rect.top += 3;
2978             }
2979             else{
2980                 rect.top += 3;
2981                 rect.bottom = rect.top + 3;
2982                 rect.right -= 3;
2983                 rect.left += 3;
2984             }
2985             draw_3d_border( dc, &rect, FALSE );
2986             release_window_dc( style, window, state_type );
2987             return;
2988         }
2989
2990     if (!GTK_IS_PANED (widget))
2991         {
2992             gint xthick, ythick;
2993             GdkGC *light_gc, *dark_gc, *shadow_gc;
2994             GdkRectangle dest;
2995
2996             sanitize_size (window, &width, &height);
2997
2998             gtk_paint_box (style, window, state_type, shadow_type, area,
2999                            widget, detail, x, y, width, height);
3000
3001             light_gc = style->light_gc[state_type];
3002             dark_gc = style->dark_gc[state_type];
3003             shadow_gc = style->mid_gc[state_type];
3004
3005             xthick = style->xthickness;
3006             ythick = style->ythickness;
3007
3008             dest.x = x + xthick;
3009             dest.y = y + ythick;
3010             dest.width = width - (xthick * 2);
3011             dest.height = height - (ythick * 2);
3012
3013             if (dest.width < dest.height)
3014                 dest.x += 2;
3015             else
3016                 dest.y += 2;
3017
3018             gdk_gc_set_clip_rectangle (light_gc, &dest);
3019             gdk_gc_set_clip_rectangle (dark_gc, &dest);
3020             gdk_gc_set_clip_rectangle (shadow_gc, &dest);
3021
3022             if (dest.width < dest.height)
3023                 {
3024                     gdk_draw_line (window, light_gc, dest.x, dest.y, dest.x,
3025                                    dest.height);
3026                     gdk_draw_line (window, dark_gc, dest.x + (dest.width / 2),
3027                                    dest.y, dest.x + (dest.width / 2),
3028                                    dest.height);
3029                     gdk_draw_line (window, shadow_gc, dest.x + dest.width,
3030                                    dest.y, dest.x + dest.width, dest.height);
3031                 }
3032             else
3033                 {
3034                     gdk_draw_line (window, light_gc, dest.x, dest.y,
3035                                    dest.x + dest.width, dest.y);
3036                     gdk_draw_line (window, dark_gc, dest.x,
3037                                    dest.y + (dest.height / 2),
3038                                    dest.x + dest.width,
3039                                    dest.y + (dest.height / 2));
3040                     gdk_draw_line (window, shadow_gc, dest.x,
3041                                    dest.y + dest.height, dest.x + dest.width,
3042                                    dest.y + dest.height);
3043                 }
3044
3045             gdk_gc_set_clip_rectangle (shadow_gc, NULL);
3046             gdk_gc_set_clip_rectangle (light_gc, NULL);
3047             gdk_gc_set_clip_rectangle (dark_gc, NULL);
3048         }
3049 }
3050
3051 static void
3052 draw_focus ( GtkStyle      *style,
3053              GdkWindow     *window,
3054              GtkStateType   state_type,
3055              GdkRectangle  *area,
3056              GtkWidget     *widget,
3057              const gchar   *detail,
3058              gint           x,
3059              gint           y,
3060              gint           width,
3061              gint           height)
3062 {
3063     HDC dc;
3064     RECT rect;
3065     if( !GTK_WIDGET_CAN_FOCUS(widget) ) {
3066         return;
3067     }
3068     if( detail && 0 == strcmp(detail, "button") 
3069         && GTK_RELIEF_NONE == gtk_button_get_relief( GTK_BUTTON(widget) ) )
3070     {
3071         return;
3072     }
3073     if ( is_combo_box_child(widget) 
3074         && (GTK_IS_ARROW(widget) || GTK_IS_BUTTON(widget)) ) {
3075         return;
3076     }
3077     if (GTK_IS_TREE_VIEW (widget->parent) /* list view bheader */
3078         || GTK_IS_CLIST (widget->parent)) {
3079         return;
3080     }
3081
3082     dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
3083     DrawFocusRect(dc, &rect);
3084     release_window_dc( style, window, state_type );
3085 /*
3086     parent_class->draw_focus (style, window, state_type,
3087                                                      area, widget, detail, x, y, width, height);
3088 */
3089 }
3090
3091 static void
3092 msw_style_init_from_rc (GtkStyle * style, GtkRcStyle * rc_style)
3093 {
3094     setup_system_font (style);
3095     setup_menu_settings (gtk_settings_get_default ());
3096     setup_system_styles (style);
3097     parent_class->init_from_rc (style, rc_style);
3098 }
3099
3100 static GdkPixmap *
3101 load_bg_image (GdkColormap *colormap,
3102                GdkColor    *bg_color,
3103                const gchar *filename)
3104 {
3105   if (strcmp (filename, "<parent>") == 0)
3106     return (GdkPixmap*) GDK_PARENT_RELATIVE;
3107   else
3108     {
3109       return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,
3110                                                   bg_color,
3111                                                   filename);
3112     }
3113 }
3114
3115 static void
3116 msw_style_realize (GtkStyle * style)
3117 {
3118   GdkGCValues gc_values;
3119   GdkGCValuesMask gc_values_mask;
3120
3121   gint i;
3122
3123   for (i = 0; i < 5; i++)
3124     {
3125       style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
3126       style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
3127       style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
3128
3129       style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
3130       style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
3131       style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
3132     }
3133
3134   style->black.red = 0x0000;
3135   style->black.green = 0x0000;
3136   style->black.blue = 0x0000;
3137   gdk_colormap_alloc_color (style->colormap, &style->black, FALSE, TRUE);
3138
3139   style->white.red = 0xffff;
3140   style->white.green = 0xffff;
3141   style->white.blue = 0xffff;
3142   gdk_colormap_alloc_color (style->colormap, &style->white, FALSE, TRUE);
3143
3144   gc_values_mask = GDK_GC_FOREGROUND | GDK_GC_BACKGROUND;
3145
3146   gc_values.foreground = style->black;
3147   gc_values.background = style->white;
3148   style->black_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3149
3150   gc_values.foreground = style->white;
3151   gc_values.background = style->black;
3152   style->white_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3153
3154   gc_values_mask = GDK_GC_FOREGROUND;
3155
3156   for (i = 0; i < 5; i++)
3157     {
3158       if (style->rc_style && style->rc_style->bg_pixmap_name[i])
3159         style->bg_pixmap[i] = load_bg_image (style->colormap,
3160                                              &style->bg[i],
3161                                              style->rc_style->bg_pixmap_name[i]);
3162
3163       if (!gdk_colormap_alloc_color (style->colormap, &style->fg[i], FALSE, TRUE))
3164         g_warning ("unable to allocate color: ( %d %d %d )",
3165                    style->fg[i].red, style->fg[i].green, style->fg[i].blue);
3166       if (!gdk_colormap_alloc_color (style->colormap, &style->bg[i], FALSE, TRUE))
3167         g_warning ("unable to allocate color: ( %d %d %d )",
3168                    style->bg[i].red, style->bg[i].green, style->bg[i].blue);
3169       if (!gdk_colormap_alloc_color (style->colormap, &style->light[i], FALSE, TRUE))
3170         g_warning ("unable to allocate color: ( %d %d %d )",
3171                    style->light[i].red, style->light[i].green, style->light[i].blue);
3172       if (!gdk_colormap_alloc_color (style->colormap, &style->dark[i], FALSE, TRUE))
3173         g_warning ("unable to allocate color: ( %d %d %d )",
3174                    style->dark[i].red, style->dark[i].green, style->dark[i].blue);
3175       if (!gdk_colormap_alloc_color (style->colormap, &style->mid[i], FALSE, TRUE))
3176         g_warning ("unable to allocate color: ( %d %d %d )",
3177                    style->mid[i].red, style->mid[i].green, style->mid[i].blue);
3178       if (!gdk_colormap_alloc_color (style->colormap, &style->text[i], FALSE, TRUE))
3179         g_warning ("unable to allocate color: ( %d %d %d )",
3180                    style->text[i].red, style->text[i].green, style->text[i].blue);
3181       if (!gdk_colormap_alloc_color (style->colormap, &style->base[i], FALSE, TRUE))
3182         g_warning ("unable to allocate color: ( %d %d %d )",
3183                    style->base[i].red, style->base[i].green, style->base[i].blue);
3184       if (!gdk_colormap_alloc_color (style->colormap, &style->text_aa[i], FALSE, TRUE))
3185         g_warning ("unable to allocate color: ( %d %d %d )",
3186                    style->text_aa[i].red, style->text_aa[i].green, style->text_aa[i].blue);
3187
3188       gc_values.foreground = style->fg[i];
3189       style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3190
3191       gc_values.foreground = style->bg[i];
3192       style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3193
3194       gc_values.foreground = style->light[i];
3195       style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3196
3197       gc_values.foreground = style->dark[i];
3198       style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3199
3200       gc_values.foreground = style->mid[i];
3201       style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3202
3203       gc_values.foreground = style->text[i];
3204       style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3205
3206       gc_values.foreground = style->base[i];
3207       style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3208
3209       gc_values.foreground = style->text_aa[i];
3210       style->text_aa_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3211     }
3212 }
3213
3214 static void
3215 msw_style_unrealize (GtkStyle * style)
3216 {
3217         parent_class->unrealize (style);
3218 }
3219
3220 static void
3221 msw_style_class_init (MswStyleClass * klass)
3222 {
3223     GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
3224
3225     parent_class = g_type_class_peek_parent (klass);
3226
3227     style_class->init_from_rc = msw_style_init_from_rc;
3228     style_class->draw_arrow = draw_arrow;
3229     style_class->draw_box = draw_box;
3230     style_class->draw_check = draw_check;
3231     style_class->draw_option = draw_option;
3232     style_class->draw_tab = draw_tab;
3233     style_class->draw_flat_box = draw_flat_box;
3234     style_class->draw_expander = draw_expander;
3235     style_class->draw_extension = draw_extension;
3236     style_class->draw_box_gap = draw_box_gap;
3237     style_class->draw_shadow = draw_shadow;
3238     style_class->draw_hline = draw_hline;
3239     style_class->draw_vline = draw_vline;
3240     style_class->draw_handle = draw_handle;
3241     style_class->draw_resize_grip = draw_resize_grip;
3242     style_class->draw_slider = draw_slider;
3243     style_class->draw_focus = draw_focus;
3244
3245     style_class->realize = msw_style_realize;
3246     style_class->unrealize = msw_style_unrealize;
3247 }
3248
3249 GType msw_type_style = 0;
3250
3251 void
3252 msw_style_register_type (GTypeModule * module)
3253 {
3254     static const GTypeInfo object_info = {
3255         sizeof (MswStyleClass),
3256         (GBaseInitFunc) NULL,
3257         (GBaseFinalizeFunc) NULL,
3258         (GClassInitFunc) msw_style_class_init,
3259         NULL,                   /* class_finalize */
3260         NULL,                   /* class_data */
3261         sizeof (MswStyle),
3262         0,                      /* n_preallocs */
3263         (GInstanceInitFunc) NULL,
3264     };
3265
3266     msw_type_style = g_type_module_register_type (module,
3267                                                   GTK_TYPE_STYLE,
3268                                                   "MswStyle",
3269                                                   &object_info, 0);
3270 }
3271
3272 void
3273 msw_style_init (void)
3274 {
3275     xp_theme_init ();
3276     msw_style_setup_system_settings ();
3277     setup_msw_rc_style ();
3278
3279     if( g_light_pen ){
3280         DeleteObject( g_light_pen );
3281         g_light_pen = NULL;
3282     }
3283     if( g_dark_pen ){
3284         DeleteObject( g_dark_pen );
3285         g_dark_pen = NULL;
3286     }
3287 }
3288
3289 void msw_style_finalize(void)
3290 {
3291     if( g_dither_brush ){
3292         DeleteObject( g_dither_brush );
3293     }
3294     if( g_light_pen ){
3295         DeleteObject( g_light_pen );
3296     }
3297     if( g_dark_pen ){
3298         DeleteObject( g_dark_pen );
3299     }
3300 }
3301