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