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