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