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