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