]> Pileus Git - ~andy/gtk/blob - modules/engines/ms-windows/msw_style.c
Bug 351678 - Notebooks not with PositionType.Top drawn incorrectly. Patch
[~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             GdkPixmap *pixmap = NULL;
2407             GdkDrawable *target = NULL;
2408             gint x2, y2, w2, h2;
2409             int tab_part = XP_THEME_ELEMENT_TAB_ITEM;
2410             int real_gap_side = gtk_notebook_get_tab_pos (notebook);
2411
2412             /* why this differs from the above gap_side, i have no idea... */
2413             if (real_gap_side == GTK_POS_LEFT || real_gap_side == GTK_POS_RIGHT)
2414               {
2415                 /* Create "rotated" pixmap.. swap width and height */
2416                 pixmap = gdk_pixmap_new (window, height, width, -1);
2417                 target = pixmap;
2418                 x2 = 0;
2419                 y2 = 0;
2420                 w2 = height;
2421                 h2 = width;
2422               }
2423             else
2424               {
2425                 target = window;
2426                 x2 = x;
2427                 y2 = y;
2428                 w2 = width;
2429                 h2 = height;
2430               }
2431
2432             if (xp_theme_draw (target, tab_part, style, x2, y2, w2, h2, state_type, NULL /*area*/))
2433                 {
2434                     GdkPixbufRotation rotation = GDK_PIXBUF_ROTATE_NONE;
2435                     if (real_gap_side == GTK_POS_BOTTOM)
2436                         rotation = GDK_PIXBUF_ROTATE_UPSIDEDOWN;
2437                     else if (real_gap_side == GTK_POS_LEFT)
2438                         rotation = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
2439                     else if (real_gap_side == GTK_POS_RIGHT)
2440                         rotation = GDK_PIXBUF_ROTATE_CLOCKWISE;
2441
2442                     if (rotation != GDK_PIXBUF_ROTATE_NONE)
2443                         {
2444                            GdkPixbuf * pixbuf, * rotated;
2445
2446                            pixbuf = gdk_pixbuf_get_from_drawable (NULL, target, NULL, x2, y2, 0, 0, w2, h2);
2447
2448                            rotated = gdk_pixbuf_rotate_simple (pixbuf, rotation);
2449                            g_object_unref (pixbuf);
2450                            pixbuf = rotated;
2451
2452                            if (real_gap_side == GTK_POS_RIGHT || real_gap_side == GTK_POS_LEFT)
2453                              {
2454                                x2 = x;
2455                                y2 = y;
2456                                w2 = width;
2457                                h2 = height;
2458                              }
2459
2460                            gdk_draw_pixbuf (window, NULL, pixbuf, 0, 0, x2, y2, w2, h2, GDK_RGB_DITHER_NONE, 0, 0);
2461
2462                            if (real_gap_side == GTK_POS_LEFT || real_gap_side == GTK_POS_RIGHT)
2463                              {
2464                                g_object_unref (pixmap);
2465                              }
2466                         }
2467                     return;
2468                 } else if (real_gap_side == GTK_POS_TOP || real_gap_side == GTK_POS_BOTTOM) {
2469                     /* experimental tab-drawing code from mozilla */
2470                     RECT rect;
2471                     HDC dc;
2472                     gint32 aPosition;
2473
2474                     dc = get_window_dc(style, window, state_type, x, y, width, height, &rect);
2475
2476                     if (real_gap_side == GTK_POS_TOP)
2477                         aPosition = BF_TOP;
2478                     else if (real_gap_side == GTK_POS_BOTTOM)
2479                         aPosition = BF_BOTTOM;
2480                     else if (real_gap_side == GTK_POS_LEFT)
2481                         aPosition = BF_LEFT;
2482                     else
2483                         aPosition = BF_RIGHT;
2484
2485                     if( state_type == GTK_STATE_PRELIGHT )
2486                         state_type = GTK_STATE_NORMAL;
2487                     if (area)
2488                         gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2489                     DrawTab (dc, rect, aPosition, state_type != GTK_STATE_PRELIGHT, (real_gap_side != GTK_POS_LEFT), (real_gap_side != GTK_POS_RIGHT));
2490                     if (area)
2491                         gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2492
2493                     release_window_dc (style, window, state_type);
2494                     return;
2495                 }
2496         }
2497     parent_class->draw_extension
2498         (style, window, state_type, shadow_type, area, widget, detail,
2499          x, y, width, height, gap_side);
2500 }
2501
2502 static void
2503 draw_box_gap (GtkStyle * style, GdkWindow * window, GtkStateType state_type,
2504               GtkShadowType shadow_type, GdkRectangle * area,
2505               GtkWidget * widget, const gchar * detail, gint x,
2506               gint y, gint width, gint height, GtkPositionType gap_side,
2507               gint gap_x, gint gap_width)
2508 {
2509     if (GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "notebook"))
2510         {
2511             if (xp_theme_draw (window, XP_THEME_ELEMENT_TAB_PANE, style, x,
2512                                   y, width, height, state_type, area))
2513                 {
2514                     return;
2515                 }
2516         }
2517     parent_class->draw_box_gap (style, window, state_type, shadow_type,
2518                                 area, widget, detail, x, y, width, height,
2519                                 gap_side, gap_x, gap_width);
2520 }
2521
2522 static gboolean is_popup_window_child( GtkWidget* widget )
2523 {
2524     GtkWidget* top;
2525     GtkWindowType type = -1;
2526
2527     top = gtk_widget_get_toplevel( widget );
2528     if( top && GTK_IS_WINDOW(top) ) {
2529         g_object_get(top, "type", &type, NULL );
2530         if( type == GTK_WINDOW_POPUP ) { /* Hack for combo boxes */
2531             return TRUE;
2532         }
2533     }
2534     return FALSE;
2535 }
2536
2537 static void
2538 draw_flat_box (GtkStyle * style, GdkWindow * window,
2539                GtkStateType state_type, GtkShadowType shadow_type,
2540                GdkRectangle * area, GtkWidget * widget,
2541                const gchar * detail, gint x, gint y, gint width, gint height)
2542 {
2543     if( detail ) {
2544         if ( !strcmp (detail, "checkbutton") )
2545         {
2546             if (state_type == GTK_STATE_PRELIGHT)
2547                 {
2548                     return;
2549                 }
2550         }
2551     }
2552
2553     parent_class->draw_flat_box (style, window, state_type, shadow_type,
2554                                  area, widget, detail, x, y, width, height);
2555 }
2556
2557 static gboolean
2558 draw_menu_border ( GdkWindow* win, GtkStyle* style, 
2559                                   gint x, gint y, gint width, gint height )
2560 {
2561     RECT rect;
2562     HDC dc;
2563
2564     dc = get_window_dc (style, win, GTK_STATE_NORMAL, x, y, width, height, &rect );
2565     if (!dc)
2566         return FALSE;
2567     if( xp_theme_is_active() ) {
2568         FrameRect( dc, &rect, GetSysColorBrush(COLOR_3DSHADOW) );
2569     }
2570     else {
2571         DrawEdge( dc, &rect, EDGE_RAISED, BF_RECT );
2572     }
2573     release_window_dc( style, win, GTK_STATE_NORMAL );
2574     return TRUE;
2575 }
2576
2577 static void
2578 draw_shadow (GtkStyle * style,
2579              GdkWindow * window,
2580              GtkStateType state_type,
2581              GtkShadowType shadow_type,
2582              GdkRectangle * area,
2583              GtkWidget * widget,
2584              const gchar * detail, gint x, gint y, gint width, gint height)
2585 {
2586     gboolean is_handlebox;
2587     gboolean is_toolbar;
2588
2589     if (is_combo_box_child (widget)
2590         && combo_box_draw_box (style, window, state_type, shadow_type,
2591                                area, widget, detail, x, y, width, height))
2592         {
2593             return;
2594         }
2595     if( detail && !strcmp( detail, "frame") )
2596         {
2597         HDC dc;
2598         RECT rect;
2599         dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
2600         if( is_popup_window_child(widget) ) {
2601             FrameRect( dc, &rect, GetSysColorBrush( COLOR_WINDOWFRAME ) );
2602         }
2603         else{
2604             switch( shadow_type ){
2605             case GTK_SHADOW_IN:
2606                 draw_3d_border(dc, &rect, TRUE);
2607                 break;
2608             case GTK_SHADOW_OUT:
2609                 draw_3d_border(dc, &rect, FALSE);
2610                 break;
2611             case GTK_SHADOW_ETCHED_IN:
2612                 draw_3d_border(dc, &rect, TRUE);
2613                 InflateRect( &rect, -1, -1 );
2614                 draw_3d_border(dc, &rect, FALSE);
2615                 break;
2616             case GTK_SHADOW_ETCHED_OUT:
2617                 draw_3d_border(dc, &rect, FALSE);
2618                 InflateRect( &rect, -1, -1 );
2619                 draw_3d_border(dc, &rect, TRUE);
2620                 break;
2621             }
2622         }
2623         release_window_dc( style, window, state_type );
2624         return;
2625     }
2626     if (detail && !strcmp (detail, "entry") )
2627         {
2628             if ( xp_theme_draw (window, XP_THEME_ELEMENT_EDIT_TEXT, style,
2629                                x, y, width, height, state_type, area))
2630                 {
2631                     return;
2632                 }
2633             if( shadow_type == GTK_SHADOW_IN ) {
2634                 HDC dc;
2635                 RECT rect;
2636                 dc = get_window_dc( style, window, state_type, 
2637                                     x, y, width, height, &rect );
2638                 DrawEdge( dc, &rect, EDGE_SUNKEN, BF_RECT );
2639                 release_window_dc( style, window, state_type );
2640                 return;
2641             }
2642         }
2643
2644     if( detail && !strcmp( detail, "spinbutton" ) )
2645                 {
2646         return;
2647     }
2648
2649     if (detail && !strcmp (detail, "menu"))
2650                         {
2651             if ( draw_menu_border ( window, style, x, y, width, height ) ) {
2652                     return;
2653                         }
2654                 }
2655
2656     if (detail && !strcmp (detail, "handlebox"))
2657         return;
2658
2659     is_handlebox = (detail && !strcmp (detail, "handlebox_bin"));
2660     is_toolbar = (detail && (!strcmp (detail, "toolbar") || !strcmp(detail, "menubar")));
2661
2662     if ( is_toolbar || is_handlebox )
2663                                 {
2664         if( widget ) {
2665             HDC dc;
2666             RECT rect;
2667             HGDIOBJ old_pen;
2668             GtkPositionType pos;
2669
2670             sanitize_size (window, &width, &height);
2671
2672             if( is_handlebox ) {
2673                 pos = gtk_handle_box_get_handle_position(GTK_HANDLE_BOX(widget));
2674                 /*
2675                     If the handle box is at left side, 
2676                     we shouldn't draw its right border.
2677                     The same holds true for top, right, and bottom.
2678                 */
2679                 switch( pos ) {
2680                 case GTK_POS_LEFT:
2681                     pos = GTK_POS_RIGHT;    break;
2682                 case GTK_POS_RIGHT:
2683                     pos = GTK_POS_LEFT;     break;
2684                 case GTK_POS_TOP:
2685                     pos = GTK_POS_BOTTOM;   break;
2686                 case GTK_POS_BOTTOM:
2687                     pos = GTK_POS_TOP;      break;
2688                                 }
2689                         }
2690             else {
2691                 GtkWidget* parent = gtk_widget_get_parent(widget);
2692                 /* Dirty hack for toolbars contained in handle boxes */
2693                 if( GTK_IS_HANDLE_BOX( parent ) ) {
2694                     pos = gtk_handle_box_get_handle_position( GTK_HANDLE_BOX( parent ) );
2695                         }
2696                 else {
2697                     /*
2698                         Dirty hack:
2699                         Make pos != all legal enum vaules of GtkPositionType.
2700                         So every border will be draw.
2701                     */
2702                     pos = (GtkPositionType)-1;
2703                 }
2704                                 }
2705
2706             dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
2707             if( pos != GTK_POS_LEFT ) {
2708                 old_pen = SelectObject( dc, get_light_pen() );
2709                 MoveToEx( dc, rect.left, rect.top, NULL );
2710                 LineTo( dc, rect.left, rect.bottom );
2711                                 }
2712             if( pos != GTK_POS_TOP ) {
2713                 old_pen = SelectObject( dc, get_light_pen() );
2714                 MoveToEx( dc, rect.left, rect.top, NULL );
2715                 LineTo( dc, rect.right, rect.top );
2716                         }
2717             if( pos != GTK_POS_RIGHT ) {
2718                 old_pen = SelectObject( dc, get_dark_pen() );
2719                 MoveToEx( dc, rect.right-1, rect.top, NULL );
2720                 LineTo( dc, rect.right-1, rect.bottom );
2721                         }
2722             if( pos != GTK_POS_BOTTOM ) {
2723                 old_pen = SelectObject( dc, get_dark_pen() );
2724                 MoveToEx( dc, rect.left, rect.bottom-1, NULL );
2725                 LineTo( dc, rect.right, rect.bottom-1 );
2726                 }
2727             SelectObject( dc, old_pen );
2728             release_window_dc( style, window, state_type );
2729                         }
2730         return;
2731                 }
2732
2733     if (detail && !strcmp (detail, "statusbar")) {
2734             return;
2735         }
2736
2737     parent_class->draw_shadow (style, window, state_type, shadow_type, area,
2738                                widget, detail, x, y, width, height);
2739 }
2740
2741 static void
2742 draw_hline (GtkStyle * style,
2743             GdkWindow * window,
2744             GtkStateType state_type,
2745             GdkRectangle * area,
2746             GtkWidget * widget,
2747             const gchar * detail, gint x1, gint x2, gint y)
2748 {
2749   if (xp_theme_is_active () && detail && !strcmp(detail, "menuitem")) {
2750         if(xp_theme_draw (window, XP_THEME_ELEMENT_MENU_SEPARATOR, style, x1, y, x2, 1, state_type, area))
2751                 return;
2752         else {
2753             if (area)
2754               gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2755
2756             gdk_draw_line (window, style->dark_gc[state_type], x1, y, x2, y);
2757
2758             if (area)
2759               gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2760         }
2761   } else {
2762       if( style->ythickness == 2 )
2763       {
2764         if (area)
2765         {
2766           gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2767           gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
2768         }
2769         gdk_draw_line (window, style->dark_gc[state_type], x1, y, x2, y);
2770         ++y;
2771         gdk_draw_line (window, style->light_gc[state_type], x1, y, x2, y);
2772         if (area)
2773         {
2774           gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2775           gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
2776         }
2777       }
2778       else
2779       {
2780     parent_class->draw_hline (style, window, state_type, area, widget,
2781                               detail, x1, x2, y);
2782   }
2783   }
2784 }
2785
2786 static void
2787 draw_vline (GtkStyle * style,
2788             GdkWindow * window,
2789             GtkStateType state_type,
2790             GdkRectangle * area,
2791             GtkWidget * widget,
2792             const gchar * detail, gint y1, gint y2, gint x)
2793 {
2794   if( style->xthickness == 2 )
2795   {
2796     if (area)
2797     {
2798       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2799       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
2800     }
2801     gdk_draw_line (window, style->dark_gc[state_type], x, y1, x, y2);
2802     ++x;
2803     gdk_draw_line (window, style->light_gc[state_type], x, y1, x, y2);
2804     if (area)
2805     {
2806       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2807       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
2808     }
2809   }
2810   else
2811   {
2812     parent_class->draw_vline (style, window, state_type, area, widget,
2813                               detail, y1, y2, x);
2814   }
2815 }
2816
2817 static void
2818 draw_slider (GtkStyle * style,
2819              GdkWindow * window,
2820              GtkStateType state_type,
2821              GtkShadowType shadow_type,
2822              GdkRectangle * area,
2823              GtkWidget * widget,
2824              const gchar * detail,
2825              gint x,
2826              gint y, gint width, gint height, GtkOrientation orientation)
2827 {
2828     if (GTK_IS_SCALE (widget) &&
2829         xp_theme_draw (window,
2830                        ((orientation ==
2831                          GTK_ORIENTATION_VERTICAL) ?
2832                         XP_THEME_ELEMENT_SCALE_SLIDER_V :
2833                         XP_THEME_ELEMENT_SCALE_SLIDER_H), style, x, y, width,
2834                        height, state_type, area))
2835         {
2836             return;
2837         }
2838
2839     parent_class->draw_slider (style, window, state_type, shadow_type, area,
2840                                widget, detail, x, y, width, height,
2841                                orientation);
2842 }
2843
2844 static void
2845 draw_resize_grip (GtkStyle * style,
2846                   GdkWindow * window,
2847                   GtkStateType state_type,
2848                   GdkRectangle * area,
2849                   GtkWidget * widget,
2850                   const gchar * detail,
2851                   GdkWindowEdge edge, gint x, gint y, gint width, gint height)
2852 {
2853     if (detail && !strcmp (detail, "statusbar"))
2854         {
2855             if (xp_theme_draw
2856                 (window, XP_THEME_ELEMENT_STATUS_GRIPPER, style, x, y, width,
2857                  height, state_type, area))
2858                         return;
2859                 else {
2860                         RECT rect;
2861                         HDC dc = get_window_dc(style, window, state_type, x, y, width, height, &rect);
2862
2863                         if (area)
2864                                 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2865                         DrawFrameControl(dc, &rect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
2866                         release_window_dc(style, window, state_type);
2867                         if (area)
2868                                 gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2869                         return;
2870                 }
2871         }
2872
2873     parent_class->draw_resize_grip (style, window, state_type, area,
2874                                     widget, detail, edge, x, y, width,
2875                                     height);
2876 }
2877
2878 static void
2879 draw_handle (GtkStyle * style,
2880              GdkWindow * window,
2881              GtkStateType state_type,
2882              GtkShadowType shadow_type,
2883              GdkRectangle * area,
2884              GtkWidget * widget,
2885              const gchar * detail,
2886              gint x,
2887              gint y, gint width, gint height, GtkOrientation orientation)
2888 {
2889     HDC dc;
2890     RECT rect;
2891
2892     if (is_toolbar_child (widget))
2893         {
2894             XpThemeElement hndl;
2895
2896             sanitize_size (window, &width, &height);
2897
2898             if( GTK_IS_HANDLE_BOX(widget) ) {
2899                 GtkPositionType pos;
2900                 pos = gtk_handle_box_get_handle_position(GTK_HANDLE_BOX(widget));
2901                 if( pos == GTK_POS_TOP || pos == GTK_POS_BOTTOM ) {
2902                     orientation = GTK_ORIENTATION_HORIZONTAL;
2903                 }
2904                 else {
2905                     orientation = GTK_ORIENTATION_VERTICAL;
2906                 }
2907             }
2908
2909             if ( orientation == GTK_ORIENTATION_VERTICAL )
2910                 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_V;
2911             else
2912                 hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_H;
2913
2914             if (xp_theme_draw (window, hndl, style, x, y, width, height,
2915                                state_type, area))
2916                 {
2917                     return;
2918                 }
2919
2920             dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
2921             if ( orientation == GTK_ORIENTATION_VERTICAL ) {
2922                 rect.left += 3;
2923                 rect.right = rect.left + 3;
2924                 rect.bottom -= 3;
2925                 rect.top += 3;
2926             }
2927             else{
2928                 rect.top += 3;
2929                 rect.bottom = rect.top + 3;
2930                 rect.right -= 3;
2931                 rect.left += 3;
2932             }
2933             draw_3d_border( dc, &rect, FALSE );
2934             release_window_dc( style, window, state_type );
2935             return;
2936         }
2937
2938     if (!GTK_IS_PANED (widget))
2939         {
2940             gint xthick, ythick;
2941             GdkGC *light_gc, *dark_gc, *shadow_gc;
2942             GdkRectangle dest;
2943
2944             sanitize_size (window, &width, &height);
2945
2946             gtk_paint_box (style, window, state_type, shadow_type, area,
2947                            widget, detail, x, y, width, height);
2948
2949             light_gc = style->light_gc[state_type];
2950             dark_gc = style->dark_gc[state_type];
2951             shadow_gc = style->mid_gc[state_type];
2952
2953             xthick = style->xthickness;
2954             ythick = style->ythickness;
2955
2956             dest.x = x + xthick;
2957             dest.y = y + ythick;
2958             dest.width = width - (xthick * 2);
2959             dest.height = height - (ythick * 2);
2960
2961             if (dest.width < dest.height)
2962                 dest.x += 2;
2963             else
2964                 dest.y += 2;
2965
2966             gdk_gc_set_clip_rectangle (light_gc, &dest);
2967             gdk_gc_set_clip_rectangle (dark_gc, &dest);
2968             gdk_gc_set_clip_rectangle (shadow_gc, &dest);
2969
2970             if (dest.width < dest.height)
2971                 {
2972                     gdk_draw_line (window, light_gc, dest.x, dest.y, dest.x,
2973                                    dest.height);
2974                     gdk_draw_line (window, dark_gc, dest.x + (dest.width / 2),
2975                                    dest.y, dest.x + (dest.width / 2),
2976                                    dest.height);
2977                     gdk_draw_line (window, shadow_gc, dest.x + dest.width,
2978                                    dest.y, dest.x + dest.width, dest.height);
2979                 }
2980             else
2981                 {
2982                     gdk_draw_line (window, light_gc, dest.x, dest.y,
2983                                    dest.x + dest.width, dest.y);
2984                     gdk_draw_line (window, dark_gc, dest.x,
2985                                    dest.y + (dest.height / 2),
2986                                    dest.x + dest.width,
2987                                    dest.y + (dest.height / 2));
2988                     gdk_draw_line (window, shadow_gc, dest.x,
2989                                    dest.y + dest.height, dest.x + dest.width,
2990                                    dest.y + dest.height);
2991                 }
2992
2993             gdk_gc_set_clip_rectangle (shadow_gc, NULL);
2994             gdk_gc_set_clip_rectangle (light_gc, NULL);
2995             gdk_gc_set_clip_rectangle (dark_gc, NULL);
2996         }
2997 }
2998
2999 static void
3000 draw_focus ( GtkStyle      *style,
3001              GdkWindow     *window,
3002              GtkStateType   state_type,
3003              GdkRectangle  *area,
3004              GtkWidget     *widget,
3005              const gchar   *detail,
3006              gint           x,
3007              gint           y,
3008              gint           width,
3009              gint           height)
3010 {
3011     HDC dc;
3012     RECT rect;
3013     if( !GTK_WIDGET_CAN_FOCUS(widget) ) {
3014         return;
3015     }
3016     if( detail && 0 == strcmp(detail, "button") 
3017         && GTK_RELIEF_NONE == gtk_button_get_relief( GTK_BUTTON(widget) ) )
3018     {
3019         return;
3020     }
3021     if ( is_combo_box_child(widget) 
3022         && (GTK_IS_ARROW(widget) || GTK_IS_BUTTON(widget)) ) {
3023         return;
3024     }
3025     if (GTK_IS_TREE_VIEW (widget->parent) /* list view bheader */
3026         || GTK_IS_CLIST (widget->parent)) {
3027         return;
3028     }
3029
3030     dc = get_window_dc( style, window, state_type, x, y, width, height, &rect );
3031     DrawFocusRect(dc, &rect);
3032     release_window_dc( style, window, state_type );
3033 /*
3034     parent_class->draw_focus (style, window, state_type,
3035                                                      area, widget, detail, x, y, width, height);
3036 */
3037 }
3038
3039 static void
3040 msw_style_init_from_rc (GtkStyle * style, GtkRcStyle * rc_style)
3041 {
3042     setup_system_font (style);
3043     setup_menu_settings (gtk_settings_get_default ());
3044     setup_system_styles (style);
3045     parent_class->init_from_rc (style, rc_style);
3046 }
3047
3048 static GdkPixmap *
3049 load_bg_image (GdkColormap *colormap,
3050                GdkColor    *bg_color,
3051                const gchar *filename)
3052 {
3053   if (strcmp (filename, "<parent>") == 0)
3054     return (GdkPixmap*) GDK_PARENT_RELATIVE;
3055   else
3056     {
3057       return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,
3058                                                   bg_color,
3059                                                   filename);
3060     }
3061 }
3062
3063 static void
3064 msw_style_realize (GtkStyle * style)
3065 {
3066   GdkGCValues gc_values;
3067   GdkGCValuesMask gc_values_mask;
3068
3069   gint i;
3070
3071   for (i = 0; i < 5; i++)
3072     {
3073       style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
3074       style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
3075       style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
3076
3077       style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
3078       style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
3079       style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
3080     }
3081
3082   style->black.red = 0x0000;
3083   style->black.green = 0x0000;
3084   style->black.blue = 0x0000;
3085   gdk_colormap_alloc_color (style->colormap, &style->black, FALSE, TRUE);
3086
3087   style->white.red = 0xffff;
3088   style->white.green = 0xffff;
3089   style->white.blue = 0xffff;
3090   gdk_colormap_alloc_color (style->colormap, &style->white, FALSE, TRUE);
3091
3092   gc_values_mask = GDK_GC_FOREGROUND | GDK_GC_BACKGROUND;
3093
3094   gc_values.foreground = style->black;
3095   gc_values.background = style->white;
3096   style->black_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3097
3098   gc_values.foreground = style->white;
3099   gc_values.background = style->black;
3100   style->white_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3101
3102   gc_values_mask = GDK_GC_FOREGROUND;
3103
3104   for (i = 0; i < 5; i++)
3105     {
3106       if (style->rc_style && style->rc_style->bg_pixmap_name[i])
3107         style->bg_pixmap[i] = load_bg_image (style->colormap,
3108                                              &style->bg[i],
3109                                              style->rc_style->bg_pixmap_name[i]);
3110
3111       if (!gdk_colormap_alloc_color (style->colormap, &style->fg[i], FALSE, TRUE))
3112         g_warning ("unable to allocate color: ( %d %d %d )",
3113                    style->fg[i].red, style->fg[i].green, style->fg[i].blue);
3114       if (!gdk_colormap_alloc_color (style->colormap, &style->bg[i], FALSE, TRUE))
3115         g_warning ("unable to allocate color: ( %d %d %d )",
3116                    style->bg[i].red, style->bg[i].green, style->bg[i].blue);
3117       if (!gdk_colormap_alloc_color (style->colormap, &style->light[i], FALSE, TRUE))
3118         g_warning ("unable to allocate color: ( %d %d %d )",
3119                    style->light[i].red, style->light[i].green, style->light[i].blue);
3120       if (!gdk_colormap_alloc_color (style->colormap, &style->dark[i], FALSE, TRUE))
3121         g_warning ("unable to allocate color: ( %d %d %d )",
3122                    style->dark[i].red, style->dark[i].green, style->dark[i].blue);
3123       if (!gdk_colormap_alloc_color (style->colormap, &style->mid[i], FALSE, TRUE))
3124         g_warning ("unable to allocate color: ( %d %d %d )",
3125                    style->mid[i].red, style->mid[i].green, style->mid[i].blue);
3126       if (!gdk_colormap_alloc_color (style->colormap, &style->text[i], FALSE, TRUE))
3127         g_warning ("unable to allocate color: ( %d %d %d )",
3128                    style->text[i].red, style->text[i].green, style->text[i].blue);
3129       if (!gdk_colormap_alloc_color (style->colormap, &style->base[i], FALSE, TRUE))
3130         g_warning ("unable to allocate color: ( %d %d %d )",
3131                    style->base[i].red, style->base[i].green, style->base[i].blue);
3132       if (!gdk_colormap_alloc_color (style->colormap, &style->text_aa[i], FALSE, TRUE))
3133         g_warning ("unable to allocate color: ( %d %d %d )",
3134                    style->text_aa[i].red, style->text_aa[i].green, style->text_aa[i].blue);
3135
3136       gc_values.foreground = style->fg[i];
3137       style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3138
3139       gc_values.foreground = style->bg[i];
3140       style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3141
3142       gc_values.foreground = style->light[i];
3143       style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3144
3145       gc_values.foreground = style->dark[i];
3146       style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3147
3148       gc_values.foreground = style->mid[i];
3149       style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3150
3151       gc_values.foreground = style->text[i];
3152       style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3153
3154       gc_values.foreground = style->base[i];
3155       style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3156
3157       gc_values.foreground = style->text_aa[i];
3158       style->text_aa_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
3159     }
3160 }
3161
3162 static void
3163 msw_style_unrealize (GtkStyle * style)
3164 {
3165         parent_class->unrealize (style);
3166 }
3167
3168 static void
3169 msw_style_class_init (MswStyleClass * klass)
3170 {
3171     GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
3172
3173     parent_class = g_type_class_peek_parent (klass);
3174
3175     style_class->init_from_rc = msw_style_init_from_rc;
3176     style_class->draw_arrow = draw_arrow;
3177     style_class->draw_box = draw_box;
3178     style_class->draw_check = draw_check;
3179     style_class->draw_option = draw_option;
3180     style_class->draw_tab = draw_tab;
3181     style_class->draw_flat_box = draw_flat_box;
3182     style_class->draw_expander = draw_expander;
3183     style_class->draw_extension = draw_extension;
3184     style_class->draw_box_gap = draw_box_gap;
3185     style_class->draw_shadow = draw_shadow;
3186     style_class->draw_hline = draw_hline;
3187     style_class->draw_vline = draw_vline;
3188     style_class->draw_handle = draw_handle;
3189     style_class->draw_resize_grip = draw_resize_grip;
3190     style_class->draw_slider = draw_slider;
3191     style_class->draw_focus = draw_focus;
3192
3193     style_class->realize = msw_style_realize;
3194     style_class->unrealize = msw_style_unrealize;
3195 }
3196
3197 GType msw_type_style = 0;
3198
3199 void
3200 msw_style_register_type (GTypeModule * module)
3201 {
3202     static const GTypeInfo object_info = {
3203         sizeof (MswStyleClass),
3204         (GBaseInitFunc) NULL,
3205         (GBaseFinalizeFunc) NULL,
3206         (GClassInitFunc) msw_style_class_init,
3207         NULL,                   /* class_finalize */
3208         NULL,                   /* class_data */
3209         sizeof (MswStyle),
3210         0,                      /* n_preallocs */
3211         (GInstanceInitFunc) NULL,
3212     };
3213
3214     msw_type_style = g_type_module_register_type (module,
3215                                                   GTK_TYPE_STYLE,
3216                                                   "MswStyle",
3217                                                   &object_info, 0);
3218 }
3219
3220 void
3221 msw_style_init (void)
3222 {
3223     xp_theme_init ();
3224     msw_style_setup_system_settings ();
3225     setup_msw_rc_style ();
3226
3227     if( g_light_pen ){
3228         DeleteObject( g_light_pen );
3229         g_light_pen = NULL;
3230     }
3231     if( g_dark_pen ){
3232         DeleteObject( g_dark_pen );
3233         g_dark_pen = NULL;
3234     }
3235 }
3236
3237 void msw_style_finalize(void)
3238 {
3239     if( g_dither_brush ){
3240         DeleteObject( g_dither_brush );
3241     }
3242     if( g_light_pen ){
3243         DeleteObject( g_light_pen );
3244     }
3245     if( g_dark_pen ){
3246         DeleteObject( g_dark_pen );
3247     }
3248 }
3249