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