]> Pileus Git - ~andy/gtk/blob - modules/engines/ms-windows/msw_style.c
Make the ms-windows theme engine build with mingw.
[~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 #include "msw_style.h"
24 #include "xp_theme.h"
25
26 #include <windows.h>
27 #include <math.h>
28 #include <string.h>
29 #include <stdio.h>
30
31 #include "gtk/gtk.h"
32 #include "gtk/gtk.h"
33 #include "gdk/win32/gdkwin32.h"
34
35
36 /* Default values, not normally used
37  */
38 static const GtkRequisition default_option_indicator_size = { 9, 8 };
39 static const GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
40
41 static GtkStyleClass *parent_class;
42
43 typedef enum {
44   CHECK_AA,
45   CHECK_BASE,
46   CHECK_BLACK,
47   CHECK_DARK,
48   CHECK_LIGHT,
49   CHECK_MID,
50   CHECK_TEXT,
51   RADIO_BASE,
52   RADIO_BLACK,
53   RADIO_DARK,
54   RADIO_LIGHT,
55   RADIO_MID,
56   RADIO_TEXT
57 } Part;
58
59 #define PART_SIZE 13
60
61 static const char check_aa_bits[] = {
62  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
63  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
64 static const char check_base_bits[] = {
65  0x00,0x00,0x00,0x00,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,
66  0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0x00,0x00,0x00,0x00};
67 static const char check_black_bits[] = {
68  0x00,0x00,0xfe,0x0f,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
69  0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00};
70 static const char check_dark_bits[] = {
71  0xff,0x1f,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
72  0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00};
73 static const char check_light_bits[] = {
74  0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,
75  0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0xfe,0x1f};
76 static const char check_mid_bits[] = {
77  0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,
78  0x08,0x00,0x08,0x00,0x08,0x00,0x08,0xfc,0x0f,0x00,0x00};
79 static const char check_text_bits[] = {
80  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x88,0x03,0xd8,0x01,0xf8,
81  0x00,0x70,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
82 static const char radio_base_bits[] = {
83  0x00,0x00,0x00,0x00,0xf0,0x01,0xf8,0x03,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,
84  0x07,0xfc,0x07,0xf8,0x03,0xf0,0x01,0x00,0x00,0x00,0x00};
85 static const char radio_black_bits[] = {
86  0x00,0x00,0xf0,0x01,0x0c,0x02,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
87  0x00,0x02,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
88 static const char radio_dark_bits[] = {
89  0xf0,0x01,0x0c,0x06,0x02,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
90  0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00};
91 static const char radio_light_bits[] = {
92  0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x10,0x00,
93  0x10,0x00,0x10,0x00,0x08,0x00,0x08,0x0c,0x06,0xf0,0x01};
94 static const char radio_mid_bits[] = {
95  0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x08,0x00,
96  0x08,0x00,0x08,0x00,0x04,0x0c,0x06,0xf0,0x01,0x00,0x00};
97 static const char radio_text_bits[] = {
98  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0xf0,0x01,0xf0,0x01,0xf0,
99  0x01,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
100
101 static struct {
102   const char *bits;
103   GdkBitmap  *bmap;
104 } parts[] = {
105   { check_aa_bits, NULL },
106   { check_base_bits, NULL },
107   { check_black_bits, NULL },
108   { check_dark_bits, NULL },
109   { check_light_bits, NULL },
110   { check_mid_bits, NULL },
111   { check_text_bits, NULL },
112   { radio_base_bits, NULL },
113   { radio_black_bits, NULL },
114   { radio_dark_bits, NULL },
115   { radio_light_bits, NULL },
116   { radio_mid_bits, NULL },
117   { radio_text_bits, NULL }
118 };
119
120 static gboolean
121 get_system_font(XpThemeClass klazz, XpThemeFont type, LOGFONT *out_lf)
122 {
123 #if 0
124   /* TODO: this crashes. need to figure out why and how to fix it */
125   if (xp_theme_get_system_font(klazz, type, out_lf))
126     return TRUE;
127   else
128 #endif
129   {
130           NONCLIENTMETRICS ncm;
131           ncm.cbSize = sizeof(NONCLIENTMETRICS);
132
133           if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
134                                    sizeof(NONCLIENTMETRICS), &ncm, 0))
135             {
136               if (type == XP_THEME_FONT_CAPTION)
137                 *out_lf = ncm.lfCaptionFont;
138               else if (type == XP_THEME_FONT_MENU)
139                 *out_lf = ncm.lfMenuFont;
140               else if (type == XP_THEME_FONT_STATUS)
141                 *out_lf = ncm.lfStatusFont;
142               else
143                 *out_lf = ncm.lfMessageFont;
144
145               return TRUE;
146             }
147   }
148   return FALSE;
149 }
150
151 /***************************** STOLEN FROM PANGO *****************************/
152
153 /*
154         This code is stolen from Pango 1.4. It attempts to address the following problems:
155
156         http://bugzilla.gnome.org/show_bug.cgi?id=135098
157         http://sourceforge.net/tracker/index.php?func=detail&aid=895762&group_id=76416&atid=547655
158
159         As Owen suggested in bug 135098, once Pango 1.6 is released, we need to get rid of this code.
160 */
161
162 #define PING(printlist)
163
164 /* TrueType defines: */
165
166 #define MAKE_TT_TABLE_NAME(c1, c2, c3, c4) \
167    (((guint32)c4) << 24 | ((guint32)c3) << 16 | ((guint32)c2) << 8 | ((guint32)c1))
168
169 #define CMAP (MAKE_TT_TABLE_NAME('c','m','a','p'))
170 #define CMAP_HEADER_SIZE 4
171
172 #define NAME (MAKE_TT_TABLE_NAME('n','a','m','e'))
173 #define NAME_HEADER_SIZE 6
174
175 #define ENCODING_TABLE_SIZE 8
176
177 #define APPLE_UNICODE_PLATFORM_ID 0
178 #define MACINTOSH_PLATFORM_ID 1
179 #define ISO_PLATFORM_ID 2
180 #define MICROSOFT_PLATFORM_ID 3
181
182 #define SYMBOL_ENCODING_ID 0
183 #define UNICODE_ENCODING_ID 1
184 #define UCS4_ENCODING_ID 10
185
186 struct name_header
187 {
188   guint16 format_selector;
189   guint16 num_records;
190   guint16 string_storage_offset;
191 };
192
193 struct name_record
194 {
195   guint16 platform_id;
196   guint16 encoding_id;
197   guint16 language_id;
198   guint16 name_id;
199   guint16 string_length;
200   guint16 string_offset;
201 };
202
203 gboolean
204 pango_win32_get_name_header (HDC                 hdc,
205                              struct name_header *header)
206 {
207   if (GetFontData (hdc, NAME, 0, header, sizeof (*header)) != sizeof (*header))
208     return FALSE;
209
210   header->num_records = GUINT16_FROM_BE (header->num_records);
211   header->string_storage_offset = GUINT16_FROM_BE (header->string_storage_offset);
212
213   return TRUE;
214 }
215
216 gboolean
217 pango_win32_get_name_record (HDC                 hdc,
218                              gint                i,
219                              struct name_record *record)
220 {
221   if (GetFontData (hdc, NAME, 6 + i * sizeof (*record),
222                    record, sizeof (*record)) != sizeof (*record))
223     return FALSE;
224
225   record->platform_id = GUINT16_FROM_BE (record->platform_id);
226   record->encoding_id = GUINT16_FROM_BE (record->encoding_id);
227   record->language_id = GUINT16_FROM_BE (record->language_id);
228   record->name_id = GUINT16_FROM_BE (record->name_id);
229   record->string_length = GUINT16_FROM_BE (record->string_length);
230   record->string_offset = GUINT16_FROM_BE (record->string_offset);
231
232   return TRUE;
233 }
234
235 static gchar *
236 get_family_name (LOGFONT *lfp, HDC pango_win32_hdc)
237 {
238   HFONT hfont;
239   HFONT oldhfont;
240
241   struct name_header header;
242   struct name_record record;
243
244   gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1;
245   gint name_ix;
246   gchar *codeset;
247
248   gchar *string = NULL;
249   gchar *name;
250
251   gint i, l;
252   gsize nbytes;
253
254   /* If lfFaceName is ASCII, assume it is the common (English) name
255    * for the font. Is this valid? Do some TrueType fonts have
256    * different names in French, German, etc, and does the system
257    * return these if the locale is set to use French, German, etc?
258    */
259   l = strlen (lfp->lfFaceName);
260   for (i = 0; i < l; i++)
261     if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~')
262       break;
263
264   if (i == l)
265     return g_strdup (lfp->lfFaceName);
266
267   if ((hfont = CreateFontIndirect (lfp)) == NULL)
268     goto fail0;
269
270   if ((oldhfont = SelectObject (pango_win32_hdc, hfont)) == NULL)
271     goto fail1;
272
273   if (!pango_win32_get_name_header (pango_win32_hdc, &header))
274     goto fail2;
275
276   PING (("%d name records", header.num_records));
277
278   for (i = 0; i < header.num_records; i++)
279     {
280       if (!pango_win32_get_name_record (pango_win32_hdc, i, &record))
281         goto fail2;
282
283       if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0)
284         continue;
285
286       PING(("platform:%d encoding:%d language:%04x name_id:%d",
287             record.platform_id, record.encoding_id, record.language_id, record.name_id));
288
289       if (record.platform_id == APPLE_UNICODE_PLATFORM_ID ||
290           record.platform_id == ISO_PLATFORM_ID)
291         unicode_ix = i;
292       else if (record.platform_id == MACINTOSH_PLATFORM_ID &&
293                record.encoding_id == 0 && /* Roman */
294                record.language_id == 0) /* English */
295         mac_ix = i;
296       else if (record.platform_id == MICROSOFT_PLATFORM_ID)
297         if ((microsoft_ix == -1 ||
298              PRIMARYLANGID (record.language_id) == LANG_ENGLISH) &&
299             (record.encoding_id == SYMBOL_ENCODING_ID ||
300              record.encoding_id == UNICODE_ENCODING_ID ||
301              record.encoding_id == UCS4_ENCODING_ID))
302           microsoft_ix = i;
303     }
304
305   if (microsoft_ix >= 0)
306     name_ix = microsoft_ix;
307   else if (mac_ix >= 0)
308     name_ix = mac_ix;
309   else if (unicode_ix >= 0)
310     name_ix = unicode_ix;
311   else
312     goto fail2;
313
314   if (!pango_win32_get_name_record (pango_win32_hdc, name_ix, &record))
315     goto fail2;
316
317   string = g_malloc (record.string_length + 1);
318   if (GetFontData (pango_win32_hdc, NAME,
319                    header.string_storage_offset + record.string_offset,
320                    string, record.string_length) != record.string_length)
321     goto fail2;
322
323   string[record.string_length] = '\0';
324
325   if (name_ix == microsoft_ix)
326     if (record.encoding_id == SYMBOL_ENCODING_ID ||
327         record.encoding_id == UNICODE_ENCODING_ID)
328       codeset = "UTF-16BE";
329     else
330       codeset = "UCS-4BE";
331   else if (name_ix == mac_ix)
332     codeset = "MacRoman";
333   else /* name_ix == unicode_ix */
334     codeset = "UCS-4BE";
335
336   name = g_convert (string, record.string_length, "UTF-8", codeset, NULL, &nbytes, NULL);
337   if (name == NULL)
338     goto fail2;
339   g_free (string);
340
341   PING(("%s", name));
342
343   SelectObject (pango_win32_hdc, oldhfont);
344   DeleteObject (hfont);
345
346   return name;
347
348  fail2:
349   g_free (string);
350   SelectObject (pango_win32_hdc, oldhfont);
351
352  fail1:
353   DeleteObject (hfont);
354
355  fail0:
356   return g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
357 }
358
359 /***************************** STOLEN FROM PANGO *****************************/
360
361 static char *
362 sys_font_to_pango_font (XpThemeClass klazz, XpThemeFont type, char * buf, size_t bufsiz)
363 {
364   HDC hDC;
365   HWND hwnd;
366   LOGFONT lf;
367   int pt_size;
368   const char * weight;
369   const char * style;
370   char * font;
371
372   if (get_system_font(klazz, type, &lf))
373     {
374       switch (lf.lfWeight) {
375       case FW_THIN:
376       case FW_EXTRALIGHT:
377         weight = "Ultra-Light";
378         break;
379
380       case FW_LIGHT:
381         weight = "Light";
382         break;
383
384       case FW_BOLD:
385         weight = "Bold";
386         break;
387
388       case FW_SEMIBOLD:
389         weight = "Semi-Bold";
390         break;
391
392       case FW_ULTRABOLD:
393         weight = "Ultra-Bold";
394         break;
395
396       case FW_HEAVY:
397         weight = "Heavy";
398         break;
399
400       default:
401         weight = "";
402         break;
403       }
404
405       if (lf.lfItalic)
406         style="Italic";
407       else
408         style="";
409
410         hwnd = GetDesktopWindow();
411         hDC = GetDC(hwnd);
412         if (hDC) {
413                 pt_size = -MulDiv(lf.lfHeight, 72,
414                               GetDeviceCaps(hDC,LOGPIXELSY));
415                 ReleaseDC(hwnd, hDC);
416         } else
417                 pt_size = 10;
418
419         font = get_family_name(&lf, hDC);
420     g_snprintf(buf, bufsiz, "%s %s %s %d", font, style, weight, pt_size);
421         g_free(font);
422
423     return buf;
424    }
425
426   return NULL;
427 }
428
429 /* missing from ms's header files */
430 #ifndef SPI_GETMENUSHOWDELAY
431 #define SPI_GETMENUSHOWDELAY 106
432 #endif
433
434 /* I don't know the proper XP theme class for things like
435    HIGHLIGHTTEXT, so we'll just define it to be "BUTTON"
436    for now */
437 #define XP_THEME_CLASS_TEXT XP_THEME_CLASS_BUTTON
438
439 static void
440 setup_menu_settings (GtkSettings * settings)
441 {
442   int menu_delay;
443   gboolean win95 = FALSE;
444   OSVERSIONINFOEX osvi;
445   GObjectClass * klazz = G_OBJECT_GET_CLASS(G_OBJECT(settings));
446
447   ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
448   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
449
450   if (!GetVersionEx ( (OSVERSIONINFO *) &osvi))
451     win95 = TRUE; /* assume the worst */
452
453   if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
454     if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
455       win95 = TRUE;
456
457   if (!win95) {
458     if (SystemParametersInfo (SPI_GETMENUSHOWDELAY, 0, &menu_delay, 0)) {
459       if (klazz) {
460         if (g_object_class_find_property (klazz, "gtk-menu-bar-popup-delay")) {
461           g_object_set (G_OBJECT (settings), "gtk-menu-bar-popup-delay",
462                         0, NULL);
463         }
464         if (g_object_class_find_property (klazz, "gtk-menu-popup-delay")) {
465           g_object_set (G_OBJECT (settings), "gtk-menu-popup-delay",
466                         menu_delay, NULL);
467         }
468         if (g_object_class_find_property (klazz, "gtk-menu-popdown-delay")) {
469           g_object_set (G_OBJECT (settings), "gtk-menu-popdown-delay",
470                         menu_delay, NULL);
471         }
472       }
473     }
474   }
475 }
476
477 void
478 msw_style_setup_system_settings (void)
479 {
480   GtkSettings * settings;
481   int cursor_blink_time;
482
483   settings = gtk_settings_get_default ();
484   if (!settings)
485     return;
486
487   cursor_blink_time = GetCaretBlinkTime ();
488   g_object_set (G_OBJECT (settings), "gtk-cursor-blink",
489                         cursor_blink_time > 0, NULL);
490
491   if (cursor_blink_time > 0)
492   {
493         g_object_set (G_OBJECT (settings), "gtk-cursor-blink-time",
494                                         2*cursor_blink_time, NULL);
495   }
496
497   g_object_set (G_OBJECT (settings), "gtk-double-click-time",
498                 GetDoubleClickTime(), NULL);
499   g_object_set (G_OBJECT (settings), "gtk-dnd-drag-threshold",
500                 GetSystemMetrics(SM_CXDRAG), NULL);
501
502   setup_menu_settings (settings);
503
504   /*
505      http://developer.gnome.org/doc/API/2.0/gtk/GtkSettings.html
506      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/systemparametersinfo.asp
507      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getsystemmetrics.asp
508   */
509 }
510
511 static void
512 setup_system_font(GtkStyle *style)
513 {
514   char buf[256], * font; /* It's okay, lfFaceName is smaller than 32 chars */
515
516   if ((font = sys_font_to_pango_font(XP_THEME_CLASS_TEXT,
517                                      XP_THEME_FONT_MESSAGE,
518                                      buf, sizeof (buf))) != NULL)
519     {
520       if (style->font_desc)
521         pango_font_description_free (style->font_desc);
522
523       style->font_desc = pango_font_description_from_string(font);
524     }
525 }
526
527 static void
528 sys_color_to_gtk_color(XpThemeClass klazz, int id, GdkColor *pcolor)
529 {
530   DWORD color;
531
532   if (!xp_theme_get_system_color (klazz, id, &color))
533         color = GetSysColor(id);
534
535   pcolor->pixel = color;
536   pcolor->red   = (GetRValue(color) << 8) | GetRValue(color);
537   pcolor->green = (GetGValue(color) << 8) | GetGValue(color);
538   pcolor->blue  = (GetBValue(color) << 8) | GetBValue(color);
539 }
540
541 static int
542 get_system_metric(XpThemeClass klazz, int id)
543 {
544   int rval;
545
546   if (!xp_theme_get_system_metric(klazz, id, &rval))
547     rval = GetSystemMetrics (id);
548
549   return rval;
550 }
551
552 static void
553 setup_msw_rc_style(void)
554 {
555   /* TODO: Owen says:
556          "If your setup_system_styles() function called gtk_rc_parse_string(), then you are just piling a new set of strings on top each time the theme changes .. the old ones won't be removed" */
557
558   char buf[1024], font_buf[256], *font_ptr;
559
560   GdkColor menu_color;
561   GdkColor menu_text_color;
562   GdkColor tooltip_back;
563   GdkColor tooltip_fore;
564   GdkColor btn_fore;
565   GdkColor btn_face;
566   GdkColor progress_back;
567
568   GdkColor fg_prelight;
569   GdkColor bg_prelight;
570   GdkColor base_prelight;
571   GdkColor text_prelight;
572
573   NONCLIENTMETRICS nc;
574
575   /* Prelight */
576   sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT, &fg_prelight);
577   sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &bg_prelight);
578   sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHT, &base_prelight);
579   sys_color_to_gtk_color(XP_THEME_CLASS_TEXT, COLOR_HIGHLIGHTTEXT, &text_prelight);
580
581   sys_color_to_gtk_color(XP_THEME_CLASS_MENU, COLOR_MENUTEXT, &menu_text_color);
582   sys_color_to_gtk_color(XP_THEME_CLASS_MENU, COLOR_MENU, &menu_color);
583
584   /* tooltips */
585   sys_color_to_gtk_color(XP_THEME_CLASS_TOOLTIP, COLOR_INFOTEXT, &tooltip_fore);
586   sys_color_to_gtk_color(XP_THEME_CLASS_TOOLTIP, COLOR_INFOBK, &tooltip_back);
587
588   /* text on push buttons. TODO: button shadows, backgrounds, and highlights */
589   sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, &btn_fore);
590   sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_BTNFACE, &btn_face);
591
592   /* progress bar background color */
593   sys_color_to_gtk_color(XP_THEME_CLASS_PROGRESS, COLOR_HIGHLIGHT, &progress_back);
594
595   /* Enable coloring for menus. */
596   font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_MENU, XP_THEME_FONT_MENU,font_buf, sizeof (font_buf));
597   g_snprintf(buf, sizeof (buf),
598              "style \"msw-menu\" = \"msw-default\"\n"
599              "{\n"
600              "fg[PRELIGHT] = { %d, %d, %d }\n"
601              "bg[PRELIGHT] = { %d, %d, %d }\n"
602              "text[PRELIGHT] = { %d, %d, %d }\n"
603              "base[PRELIGHT] = { %d, %d, %d }\n"
604              "fg[NORMAL] = { %d, %d, %d }\n"
605              "bg[NORMAL] = { %d, %d, %d }\n"
606              "%s = \"%s\"\n"
607              "}widget_class \"*MenuItem*\" style \"msw-menu\"\n"
608              "widget_class \"*GtkMenu\" style \"msw-menu\"\n"
609              "widget_class \"*GtkMenuShell*\" style \"msw-menu\"\n",
610              fg_prelight.red,
611              fg_prelight.green,
612              fg_prelight.blue,
613              bg_prelight.red,
614              bg_prelight.green,
615              bg_prelight.blue,
616              text_prelight.red,
617              text_prelight.green,
618              text_prelight.blue,
619              base_prelight.red,
620              base_prelight.green,
621              base_prelight.blue,
622              menu_text_color.red,
623              menu_text_color.green,
624              menu_text_color.blue,
625              menu_color.red,
626              menu_color.green,
627              menu_color.blue,
628              (font_ptr ? "font_name" : "#"),
629              (font_ptr ? font_ptr : " font name should go here"));
630   gtk_rc_parse_string(buf);
631
632   /* Enable coloring for menu bars. */
633   g_snprintf(buf, sizeof (buf),
634              "style \"msw-menu-bar\" = \"msw-menu\"\n"
635              "{\n"
636              "bg[NORMAL] = { %d, %d, %d }\n"
637              "GtkMenuBar::shadow-type = etched-in\n"
638              "}widget_class \"*MenuBar*\" style \"msw-menu-bar\"\n",
639              btn_face.red,
640              btn_face.green,
641              btn_face.blue);
642   gtk_rc_parse_string(buf);
643
644   /* enable tooltip fonts */
645   font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,font_buf, sizeof (font_buf));
646   g_snprintf(buf, sizeof (buf),
647              "style \"msw-tooltips-caption\" = \"msw-default\"\n"
648              "{fg[NORMAL] = { %d, %d, %d }\n"
649              "%s = \"%s\"\n"
650              "}widget \"gtk-tooltips.GtkLabel\" style \"msw-tooltips-caption\"\n",
651              tooltip_fore.red,
652              tooltip_fore.green,
653              tooltip_fore.blue,
654              (font_ptr ? "font_name" : "#"),
655              (font_ptr ? font_ptr : " font name should go here"));
656   gtk_rc_parse_string(buf);
657
658   g_snprintf(buf, sizeof (buf),
659              "style \"msw-tooltips\" = \"msw-default\"\n"
660              "{bg[NORMAL] = { %d, %d, %d }\n"
661              "}widget \"gtk-tooltips*\" style \"msw-tooltips\"\n",
662              tooltip_back.red,
663              tooltip_back.green,
664              tooltip_back.blue);
665   gtk_rc_parse_string(buf);
666
667   /* enable font theming for status bars */
668   font_ptr = sys_font_to_pango_font (XP_THEME_CLASS_STATUS, XP_THEME_FONT_STATUS,font_buf, sizeof (font_buf));
669   g_snprintf(buf, sizeof (buf),
670              "style \"msw-status\" = \"msw-default\"\n"
671              "{%s = \"%s\"\n"
672              "bg[NORMAL] = { %d, %d, %d }\n"
673              "}widget_class \"*Status*\" style \"msw-status\"\n",
674              (font_ptr ? "font_name" : "#"),
675              (font_ptr ? font_ptr : " font name should go here"),
676              btn_face.red, btn_face.green, btn_face.blue);
677   gtk_rc_parse_string(buf);
678
679   /* enable coloring for text on buttons
680      TODO: use GetThemeMetric for the border and outside border */
681   g_snprintf(buf, sizeof (buf),
682              "style \"msw-button\" = \"msw-default\"\n"
683              "{\n"
684              "bg[NORMAL] = { %d, %d, %d }\n"
685              "bg[PRELIGHT] = { %d, %d, %d }\n"
686              "bg[INSENSITIVE] = { %d, %d, %d }\n"
687              "fg[PRELIGHT] = { %d, %d, %d }\n"
688              "GtkButton::default-border = { 1, 1, 1, 1 }\n"
689              "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
690              "GtkButton::child-displacement-x = 1\n"
691              "GtkButton::child-displacement-y = 1\n"
692              "}widget_class \"*Button*\" style \"msw-button\"\n",
693              btn_face.red, btn_face.green, btn_face.blue,
694              btn_face.red, btn_face.green, btn_face.blue,
695              btn_face.red, btn_face.green, btn_face.blue,
696              btn_fore.red, btn_fore.green, btn_fore.blue
697              );
698   gtk_rc_parse_string(buf);
699
700   /* enable coloring for progress bars */
701   g_snprintf(buf, sizeof (buf),
702              "style \"msw-progress\" = \"msw-default\"\n"
703              "{bg[PRELIGHT] = { %d, %d, %d }\n"
704              "bg[NORMAL] = { %d, %d, %d }\n"
705              "}widget_class \"*Progress*\" style \"msw-progress\"\n",
706              progress_back.red,
707              progress_back.green,
708              progress_back.blue,
709              btn_face.red, btn_face.green, btn_face.blue);
710   gtk_rc_parse_string(buf);
711
712   /* scrollbar thumb width and height */
713   g_snprintf(buf, sizeof (buf),
714              "style \"msw-vscrollbar\" = \"msw-default\"\n"
715              "{GtkRange::slider-width = %d\n"
716              "GtkRange::stepper-size = %d\n"
717              "GtkRange::stepper-spacing = 0\n"
718              "GtkRange::trough_border = 0\n"
719              "}widget_class \"*VScrollbar*\" style \"msw-vscrollbar\"\n",
720              GetSystemMetrics(SM_CYVTHUMB),
721              get_system_metric(XP_THEME_CLASS_SCROLLBAR, SM_CXVSCROLL));
722   gtk_rc_parse_string(buf);
723
724   g_snprintf(buf, sizeof (buf),
725              "style \"msw-hscrollbar\" = \"msw-default\"\n"
726              "{GtkRange::slider-width = %d\n"
727              "GtkRange::stepper-size = %d\n"
728              "GtkRange::stepper-spacing = 0\n"
729              "GtkRange::trough_border = 0\n"
730              "}widget_class \"*HScrollbar*\" style \"msw-hscrollbar\"\n",
731              GetSystemMetrics(SM_CXHTHUMB),
732              get_system_metric(XP_THEME_CLASS_SCROLLBAR, SM_CYHSCROLL));
733   gtk_rc_parse_string(buf);
734
735   /* radio/check button sizes */
736   g_snprintf(buf, sizeof (buf),
737              "style \"msw-checkbutton\" = \"msw-button\"\n"
738              "{GtkCheckButton::indicator-size = 13\n"
739              "}widget_class \"*CheckButton*\" style \"msw-checkbutton\"\n"
740              "widget_class \"*RadioButton*\" style \"msw-checkbutton\"\n");
741   gtk_rc_parse_string(buf);
742 }
743
744 static void
745 setup_system_styles(GtkStyle *style)
746 {
747   int i;
748
749   /* Default background */
750   sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON,  COLOR_BTNFACE,   &style->bg[GTK_STATE_NORMAL]);
751   sys_color_to_gtk_color(XP_THEME_CLASS_TEXT,    COLOR_HIGHLIGHT, &style->bg[GTK_STATE_SELECTED]);
752   sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON,  COLOR_BTNFACE,   &style->bg[GTK_STATE_INSENSITIVE]);
753   sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON,  COLOR_BTNFACE,   &style->bg[GTK_STATE_ACTIVE]);
754   sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON,  COLOR_BTNFACE,   &style->bg[GTK_STATE_PRELIGHT]);
755
756   /* Default base */
757   sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW,  COLOR_WINDOW,    &style->base[GTK_STATE_NORMAL]);
758   sys_color_to_gtk_color(XP_THEME_CLASS_TEXT,    COLOR_HIGHLIGHT, &style->base[GTK_STATE_SELECTED]);
759   sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON,  COLOR_BTNFACE,   &style->base[GTK_STATE_INSENSITIVE]);
760   sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON,  COLOR_BTNFACE,   &style->base[GTK_STATE_ACTIVE]);
761   sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW,  COLOR_WINDOW,    &style->base[GTK_STATE_PRELIGHT]);
762
763   /* Default text */
764   sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW,  COLOR_WINDOWTEXT,    &style->text[GTK_STATE_NORMAL]);
765   sys_color_to_gtk_color(XP_THEME_CLASS_TEXT,    COLOR_HIGHLIGHTTEXT, &style->text[GTK_STATE_SELECTED]);
766   sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON,  COLOR_GRAYTEXT,      &style->text[GTK_STATE_INSENSITIVE]);
767   sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON,  COLOR_BTNTEXT,       &style->text[GTK_STATE_ACTIVE]);
768   sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW,  COLOR_WINDOWTEXT,    &style->text[GTK_STATE_PRELIGHT]);
769
770   /* Default forgeground */
771   sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON,  COLOR_BTNTEXT,       &style->fg[GTK_STATE_NORMAL]);
772   sys_color_to_gtk_color(XP_THEME_CLASS_TEXT,    COLOR_HIGHLIGHTTEXT, &style->fg[GTK_STATE_SELECTED]);
773   sys_color_to_gtk_color(XP_THEME_CLASS_TEXT,    COLOR_GRAYTEXT,      &style->fg[GTK_STATE_INSENSITIVE]);
774   sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON,  COLOR_BTNTEXT,       &style->fg[GTK_STATE_ACTIVE]);
775   sys_color_to_gtk_color(XP_THEME_CLASS_WINDOW,  COLOR_WINDOWTEXT,    &style->fg[GTK_STATE_PRELIGHT]);
776
777   for (i = 0; i < 5; i++)
778     {
779       sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_3DSHADOW, &style->dark[i]);
780       sys_color_to_gtk_color(XP_THEME_CLASS_BUTTON, COLOR_3DHILIGHT, &style->light[i]);
781
782       style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
783       style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
784       style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
785
786       style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
787       style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
788       style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
789     }
790 }
791
792 static gboolean
793 sanitize_size (GdkWindow *window,
794                gint      *width,
795                gint      *height)
796 {
797   gboolean set_bg = FALSE;
798
799   if ((*width == -1) && (*height == -1))
800     {
801       set_bg = GDK_IS_WINDOW (window);
802       gdk_drawable_get_size (window, width, height);
803     }
804   else if (*width == -1)
805     gdk_drawable_get_size (window, width, NULL);
806   else if (*height == -1)
807     gdk_drawable_get_size (window, NULL, height);
808
809   return set_bg;
810 }
811
812 static XpThemeElement
813 map_gtk_progress_bar_to_xp(GtkProgressBar *progress_bar, gboolean trough)
814 {
815   XpThemeElement ret;
816   switch (progress_bar->orientation)
817     {
818     case GTK_PROGRESS_LEFT_TO_RIGHT:
819     case GTK_PROGRESS_RIGHT_TO_LEFT:
820       ret = trough
821         ? XP_THEME_ELEMENT_PROGRESS_TROUGH_H
822         : XP_THEME_ELEMENT_PROGRESS_BAR_H;
823       break;
824     default:
825       ret = trough
826         ? XP_THEME_ELEMENT_PROGRESS_TROUGH_V
827         : XP_THEME_ELEMENT_PROGRESS_BAR_V;
828       break;
829     }
830   return ret;
831 }
832
833 static void
834 draw_part (GdkDrawable  *drawable,
835            GdkGC        *gc,
836            GdkRectangle *area,
837            gint          x,
838            gint          y,
839            Part          part)
840 {
841   if (area)
842     gdk_gc_set_clip_rectangle (gc, area);
843
844   if (!parts[part].bmap)
845       parts[part].bmap = gdk_bitmap_create_from_data (drawable,
846                                                       parts[part].bits,
847                                                       PART_SIZE, PART_SIZE);
848
849   gdk_gc_set_ts_origin (gc, x, y);
850   gdk_gc_set_stipple (gc, parts[part].bmap);
851   gdk_gc_set_fill (gc, GDK_STIPPLED);
852
853   gdk_draw_rectangle (drawable, gc, TRUE, x, y, PART_SIZE, PART_SIZE);
854
855   gdk_gc_set_fill (gc, GDK_SOLID);
856
857   if (area)
858     gdk_gc_set_clip_rectangle (gc, NULL);
859 }
860
861 static void
862 draw_check(GtkStyle      *style,
863            GdkWindow     *window,
864            GtkStateType   state,
865            GtkShadowType  shadow,
866            GdkRectangle  *area,
867            GtkWidget     *widget,
868            const gchar   *detail,
869            gint           x,
870            gint           y,
871            gint           width,
872            gint           height)
873 {
874   x -= (1 + PART_SIZE - width) / 2;
875   y -= (1 + PART_SIZE - height) / 2;
876
877   if (detail && strcmp (detail, "check") == 0)  /* Menu item */
878     {
879       if (shadow == GTK_SHADOW_IN)
880         {
881           draw_part (window, style->black_gc, area, x, y, CHECK_TEXT);
882           draw_part (window, style->dark_gc[state], area, x, y, CHECK_AA);
883         }
884     }
885   else
886     {
887       if (!xp_theme_draw(window, shadow == GTK_SHADOW_IN
888                          ? XP_THEME_ELEMENT_PRESSED_CHECKBOX
889                          : XP_THEME_ELEMENT_CHECKBOX,
890                          style, x, y, width, height, state, area))
891         {
892           draw_part (window, style->black_gc, area, x, y, CHECK_BLACK);
893           draw_part (window, style->dark_gc[state], area, x, y, CHECK_DARK);
894           draw_part (window, style->mid_gc[state], area, x, y, CHECK_MID);
895           draw_part (window, style->light_gc[state], area, x, y, CHECK_LIGHT);
896           draw_part (window, style->base_gc[state], area, x, y, CHECK_BASE);
897
898           if (shadow == GTK_SHADOW_IN)
899             {
900               draw_part (window, style->text_gc[state], area, x, y, CHECK_TEXT);
901               draw_part (window, style->text_aa_gc[state], area, x, y, CHECK_AA);
902             }
903         }
904     }
905 }
906
907 static void
908 draw_expander(GtkStyle      *style,
909               GdkWindow     *window,
910               GtkStateType   state,
911               GdkRectangle  *area,
912               GtkWidget     *widget,
913               const gchar   *detail,
914               gint           x,
915               gint           y,
916               GtkExpanderStyle expander_style)
917 {
918   gint expander_size;
919   gint expander_semi_size;
920   GdkColor color;
921   GdkGCValues values;
922   gboolean success;
923   XpThemeElement xp_expander;
924
925   gtk_widget_style_get (widget, "expander_size", &expander_size, NULL);
926
927   switch (expander_style)
928     {
929     case GTK_EXPANDER_COLLAPSED:
930     case GTK_EXPANDER_SEMI_COLLAPSED:
931       xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED;
932       break;
933     default:
934       xp_expander = XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED;
935       break;
936     }
937
938   if ((expander_size % 2) == 0)
939     expander_size--;
940
941   if (expander_size > 2)
942     expander_size -= 2;
943
944   if (area)
945     gdk_gc_set_clip_rectangle (style->fg_gc[state], area);
946
947   expander_semi_size = expander_size / 2;
948   x -= expander_semi_size;
949   y -= expander_semi_size;
950
951   gdk_gc_get_values (style->fg_gc[state], &values);
952
953   if (! xp_theme_draw(window, xp_expander, style,
954                       x, y,
955                       expander_size, expander_size, state, area))
956     {
957       /* RGB values to emulate Windows Classic style */
958       color.red = color.green = color.blue = 128 << 8;
959
960       success = gdk_colormap_alloc_color
961         (gtk_widget_get_default_colormap (), &color, FALSE, TRUE);
962
963       if (success)
964         gdk_gc_set_foreground (style->fg_gc[state], &color);
965
966       gdk_draw_rectangle
967         (window, style->fg_gc[state], FALSE, x, y,
968          expander_size - 1, expander_size - 1);
969
970       gdk_draw_line
971         (window, style->fg_gc[state], x + 2, y + expander_semi_size,
972          x + expander_size - 2, y + expander_semi_size);
973
974       switch (expander_style)
975         {
976         case GTK_EXPANDER_COLLAPSED:
977         case GTK_EXPANDER_SEMI_COLLAPSED:
978           gdk_draw_line
979             (window, style->fg_gc[state], x + expander_semi_size, y + 2,
980              x + expander_semi_size, y + expander_size - 2);
981           break;
982         }
983
984       if (success)
985         gdk_gc_set_foreground (style->fg_gc[state], &values.foreground);
986     }
987
988   if (area)
989     gdk_gc_set_clip_rectangle (style->fg_gc[state], NULL);
990 }
991
992 static void
993 draw_option(GtkStyle      *style,
994             GdkWindow     *window,
995             GtkStateType   state,
996             GtkShadowType  shadow,
997             GdkRectangle  *area,
998             GtkWidget     *widget,
999             const gchar   *detail,
1000             gint           x,
1001             gint           y,
1002             gint           width,
1003             gint           height)
1004 {
1005   x -= (1 + PART_SIZE - width) / 2;
1006   y -= (1 + PART_SIZE - height) / 2;
1007
1008   if (detail && strcmp (detail, "option") == 0) /* Menu item */
1009     {
1010       if (shadow == GTK_SHADOW_IN)
1011         draw_part (window, style->fg_gc[state], area, x, y, RADIO_TEXT);
1012     }
1013   else
1014     {
1015       if (xp_theme_draw (window, shadow == GTK_SHADOW_IN
1016                         ? XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON
1017                         : XP_THEME_ELEMENT_RADIO_BUTTON,
1018                         style, x, y, width, height, state, area))
1019         {
1020         }
1021       else
1022         {
1023           draw_part (window, style->black_gc, area, x, y, RADIO_BLACK);
1024           draw_part (window, style->dark_gc[state], area, x, y, RADIO_DARK);
1025           draw_part (window, style->mid_gc[state], area, x, y, RADIO_MID);
1026           draw_part (window, style->light_gc[state], area, x, y, RADIO_LIGHT);
1027           draw_part (window, style->base_gc[state], area, x, y, RADIO_BASE);
1028
1029           if (shadow == GTK_SHADOW_IN)
1030             draw_part (window, style->text_gc[state], area, x, y, RADIO_TEXT);
1031         }
1032     }
1033 }
1034
1035 static void
1036 draw_varrow (GdkWindow     *window,
1037              GdkGC         *gc,
1038              GtkShadowType  shadow_type,
1039              GdkRectangle  *area,
1040              GtkArrowType   arrow_type,
1041              gint           x,
1042              gint           y,
1043              gint           width,
1044              gint           height)
1045 {
1046   gint steps, extra;
1047   gint y_start, y_increment;
1048   gint i;
1049
1050   if (area)
1051     gdk_gc_set_clip_rectangle (gc, area);
1052
1053   width = width + width % 2 - 1;        /* Force odd */
1054
1055   steps = 1 + width / 2;
1056
1057   extra = height - steps;
1058
1059   if (arrow_type == GTK_ARROW_DOWN)
1060     {
1061       y_start = y;
1062       y_increment = 1;
1063     }
1064   else
1065     {
1066       y_start = y + height - 1;
1067       y_increment = -1;
1068     }
1069
1070   for (i = extra; i < height; i++)
1071     {
1072       gdk_draw_line (window, gc,
1073                      x + (i - extra),              y_start + i * y_increment,
1074                      x + width - (i - extra) - 1,  y_start + i * y_increment);
1075     }
1076
1077   if (area)
1078     gdk_gc_set_clip_rectangle (gc, NULL);
1079 }
1080
1081 static void
1082 draw_harrow (GdkWindow     *window,
1083              GdkGC         *gc,
1084              GtkShadowType  shadow_type,
1085              GdkRectangle  *area,
1086              GtkArrowType   arrow_type,
1087              gint           x,
1088              gint           y,
1089              gint           width,
1090              gint           height)
1091 {
1092   gint steps, extra;
1093   gint x_start, x_increment;
1094   gint i;
1095
1096   if (area)
1097     gdk_gc_set_clip_rectangle (gc, area);
1098
1099   height = height + height % 2 - 1;     /* Force odd */
1100
1101   steps = 1 + height / 2;
1102
1103   extra = width - steps;
1104
1105   if (arrow_type == GTK_ARROW_RIGHT)
1106     {
1107       x_start = x;
1108       x_increment = 1;
1109     }
1110   else
1111     {
1112       x_start = x + width - 1;
1113       x_increment = -1;
1114     }
1115
1116   for (i = extra; i < width; i++)
1117     {
1118       gdk_draw_line (window, gc,
1119                      x_start + i * x_increment, y + (i - extra),
1120                      x_start + i * x_increment, y + height - (i - extra) - 1);
1121     }
1122
1123
1124   if (area)
1125     gdk_gc_set_clip_rectangle (gc, NULL);
1126 }
1127
1128 /* This function makes up for some brokeness in gtkrange.c
1129  * where we never get the full arrow of the stepper button
1130  * and the type of button in a single drawing function.
1131  *
1132  * It doesn't work correctly when the scrollbar is squished
1133  * to the point we don't have room for full-sized steppers.
1134  */
1135 static void
1136 reverse_engineer_stepper_box (GtkWidget    *range,
1137                               GtkArrowType  arrow_type,
1138                               gint         *x,
1139                               gint         *y,
1140                               gint         *width,
1141                               gint         *height)
1142 {
1143   gint slider_width = 14, stepper_size = 14;
1144   gint box_width;
1145   gint box_height;
1146
1147   if (range)
1148     {
1149       gtk_widget_style_get (range,
1150                             "slider_width", &slider_width,
1151                             "stepper_size", &stepper_size,
1152                             NULL);
1153     }
1154
1155   if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1156     {
1157       box_width = slider_width;
1158       box_height = stepper_size;
1159     }
1160   else
1161     {
1162       box_width = stepper_size;
1163       box_height = slider_width;
1164     }
1165
1166   *x = *x - (box_width - *width) / 2;
1167   *y = *y - (box_height - *height) / 2;
1168   *width = box_width;
1169   *height = box_height;
1170 }
1171
1172 static void
1173 draw_arrow (GtkStyle      *style,
1174             GdkWindow     *window,
1175             GtkStateType   state,
1176             GtkShadowType  shadow,
1177             GdkRectangle  *area,
1178             GtkWidget     *widget,
1179             const gchar   *detail,
1180             GtkArrowType   arrow_type,
1181             gboolean       fill,
1182             gint           x,
1183             gint           y,
1184             gint           width,
1185             gint           height)
1186 {
1187   const gchar * name;
1188
1189   name = gtk_widget_get_name (widget);
1190
1191   sanitize_size (window, &width, &height);
1192
1193   if (detail && strcmp (detail, "spinbutton") == 0)
1194     {
1195       if (xp_theme_is_drawable(XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1196         {
1197           return;
1198         }
1199       else
1200         {
1201           x += (width - 7) / 2;
1202
1203           if (arrow_type == GTK_ARROW_UP)
1204             y += (height - 4) / 2;
1205           else
1206             y += (1 + height - 4) / 2;
1207           draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
1208                        x, y, 7, 4);
1209         }
1210     }
1211   else if (detail && (!strcmp (detail, "vscrollbar")
1212                       || !strcmp (detail, "hscrollbar")))
1213     {
1214       gboolean is_disabled = FALSE;
1215       GtkScrollbar * scrollbar = GTK_SCROLLBAR(widget);
1216       gint box_x = x;
1217       gint box_y = y;
1218       gint box_width = width;
1219       gint box_height = height;
1220       XpThemeElement xp_arrow;
1221       reverse_engineer_stepper_box (widget, arrow_type,
1222                                     &box_x, &box_y, &box_width, &box_height);
1223
1224       if (scrollbar->range.adjustment->page_size >= (scrollbar->range.adjustment->upper-scrollbar->range.adjustment->lower))
1225         is_disabled = TRUE;
1226
1227       switch (arrow_type)
1228         {
1229         case GTK_ARROW_UP:
1230           xp_arrow = XP_THEME_ELEMENT_ARROW_UP;
1231           break;
1232         case GTK_ARROW_DOWN:
1233           xp_arrow = XP_THEME_ELEMENT_ARROW_DOWN;
1234           break;
1235         case GTK_ARROW_LEFT:
1236           xp_arrow = XP_THEME_ELEMENT_ARROW_LEFT;
1237           break;
1238         default:
1239           xp_arrow = XP_THEME_ELEMENT_ARROW_RIGHT;
1240           break;
1241         }
1242       if (xp_theme_draw(window, xp_arrow, style, box_x, box_y, box_width, box_height, state, area))
1243         {
1244         }
1245       else if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1246         {
1247           x += (width - 7) / 2;
1248           y += (height - 5) / 2;
1249
1250           draw_varrow (window, is_disabled ? style->text_aa_gc[state] : style->fg_gc[state], shadow, area, arrow_type,
1251                        x, y, 7, 5);
1252         }
1253       else
1254         {
1255           y += (height - 7) / 2;
1256           x += (width - 5) / 2;
1257
1258           draw_harrow (window, is_disabled ? style->text_aa_gc[state] : style->fg_gc[state], shadow, area, arrow_type,
1259                        x, y, 5, 7);
1260         }
1261     }
1262   else
1263     {
1264       /* draw the toolbar chevrons - waiting for GTK 2.4 */
1265           if (name && !strcmp (name, "gtk-toolbar-arrow"))
1266           {
1267                   if (xp_theme_draw(window, XP_THEME_ELEMENT_REBAR_CHEVRON, style, x, y, width, height, state, area))
1268                                 return;
1269           }
1270
1271       if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
1272         {
1273           x += (width - 7) / 2;
1274           y += (height - 5) / 2;
1275
1276           draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
1277                        x, y, 7, 5);
1278         }
1279       else
1280         {
1281           x += (width - 5) / 2;
1282           y += (height - 7) / 2;
1283
1284           draw_harrow (window, style->fg_gc[state], shadow, area, arrow_type,
1285                        x, y, 5, 7);
1286         }
1287     }
1288 }
1289
1290 static void
1291 option_menu_get_props (GtkWidget      *widget,
1292                        GtkRequisition *indicator_size,
1293                        GtkBorder      *indicator_spacing)
1294 {
1295   GtkRequisition *tmp_size = NULL;
1296   GtkBorder *tmp_spacing = NULL;
1297
1298   if (widget)
1299     gtk_widget_style_get (widget,
1300                           "indicator_size", &tmp_size,
1301                           "indicator_spacing", &tmp_spacing,
1302                           NULL);
1303
1304   if (tmp_size)
1305     {
1306       *indicator_size = *tmp_size;
1307       g_free (tmp_size);
1308     }
1309   else
1310     *indicator_size = default_option_indicator_size;
1311
1312   if (tmp_spacing)
1313     {
1314       *indicator_spacing = *tmp_spacing;
1315       g_free (tmp_spacing);
1316     }
1317   else
1318     *indicator_spacing = default_option_indicator_spacing;
1319 }
1320
1321 static gboolean is_toolbar_child(GtkWidget * wid)
1322 {
1323         while(wid)
1324         {
1325                 if(GTK_IS_TOOLBAR(wid) || GTK_IS_HANDLE_BOX(wid))
1326                         return TRUE;
1327                 else
1328                         wid = wid->parent;
1329         }
1330
1331         return FALSE;
1332 }
1333
1334 static void
1335 draw_box (GtkStyle      *style,
1336           GdkWindow     *window,
1337           GtkStateType   state_type,
1338           GtkShadowType  shadow_type,
1339           GdkRectangle  *area,
1340           GtkWidget     *widget,
1341           const gchar   *detail,
1342           gint           x,
1343           gint           y,
1344           gint           width,
1345           gint           height)
1346 {
1347   if (detail &&
1348       (!strcmp (detail, "button") ||
1349        !strcmp (detail, "buttondefault")))
1350     {
1351       if (GTK_IS_TREE_VIEW (widget->parent) || GTK_IS_CLIST (widget->parent))
1352         {
1353           if (xp_theme_draw(window, XP_THEME_ELEMENT_LIST_HEADER, style, x, y,
1354                             width, height, state_type, area))
1355             return;
1356         }
1357       else if (is_toolbar_child (widget->parent))
1358       {
1359                     if (xp_theme_draw(window, XP_THEME_ELEMENT_TOOLBAR_BUTTON, style, x, y,
1360                                               width, height, state_type, area))
1361                 return;
1362           }
1363       else
1364         {
1365           gboolean is_default = !strcmp (detail, "buttondefault");
1366           if (xp_theme_draw(window, is_default ? XP_THEME_ELEMENT_DEFAULT_BUTTON
1367                             : XP_THEME_ELEMENT_BUTTON, style, x, y,
1368                             width, height, state_type, area))
1369             return;
1370         }
1371     }
1372   else if (detail && !strcmp (detail, "spinbutton"))
1373     {
1374       if (xp_theme_is_drawable(XP_THEME_ELEMENT_SPIN_BUTTON_UP))
1375         {
1376           return;
1377         }
1378     }
1379   else if (detail && (!strcmp (detail, "spinbutton_up")
1380                       || !strcmp (detail, "spinbutton_down")))
1381     {
1382       if (xp_theme_draw(window,
1383                         (! strcmp (detail, "spinbutton_up"))
1384                         ? XP_THEME_ELEMENT_SPIN_BUTTON_UP
1385                         : XP_THEME_ELEMENT_SPIN_BUTTON_DOWN,
1386                         style, x, y, width, height, state_type, area))
1387         {
1388           return;
1389         }
1390     }
1391
1392   else if (detail && !strcmp (detail, "slider"))
1393     {
1394       if (GTK_IS_SCROLLBAR(widget))
1395         {
1396           GtkScrollbar * scrollbar = GTK_SCROLLBAR(widget);
1397           gboolean is_v = GTK_IS_VSCROLLBAR(widget);
1398           if (xp_theme_draw(window,
1399                             is_v
1400                             ? XP_THEME_ELEMENT_SCROLLBAR_V
1401                             : XP_THEME_ELEMENT_SCROLLBAR_H,
1402                             style, x, y, width, height, state_type, area))
1403             {
1404               XpThemeElement gripper = (is_v ? XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V : XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H);
1405
1406               /* Do not display grippers on tiny scroll bars, the limit imposed
1407                  is rather arbitrary, perhaps we can fetch the gripper geometry
1408                  from somewhere and use that... */
1409               if ((gripper == XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H && width < 16)
1410                   || (gripper == XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V && height < 16))
1411                 {
1412                   return;
1413                 }
1414
1415               xp_theme_draw(window, gripper, style, x, y, width, height, state_type, area);
1416               return;
1417             }
1418           else
1419           {
1420             if (scrollbar->range.adjustment->page_size >= (scrollbar->range.adjustment->upper-scrollbar->range.adjustment->lower))
1421               return;
1422           }
1423         }
1424     }
1425   else if (detail && !strcmp (detail, "bar"))
1426     {
1427       if (widget && GTK_IS_PROGRESS_BAR (widget))
1428         {
1429           GtkProgressBar *progress_bar = GTK_PROGRESS_BAR(widget);
1430           XpThemeElement xp_progress_bar = map_gtk_progress_bar_to_xp (progress_bar, FALSE);
1431           if (xp_theme_draw (window, xp_progress_bar,
1432                              style, x, y, width, height, state_type, area))
1433             {
1434               return;
1435             }
1436         }
1437     }
1438   else if (detail && strcmp (detail, "menuitem") == 0) {
1439     shadow_type = GTK_SHADOW_NONE;
1440       if (xp_theme_draw (window, XP_THEME_ELEMENT_MENU_ITEM, style, x, y, width, height, state_type, area))
1441         {
1442                 return;
1443         }
1444   }
1445   else if (detail && !strcmp (detail, "trough"))
1446     {
1447       if (widget && GTK_IS_PROGRESS_BAR (widget))
1448         {
1449           GtkProgressBar *progress_bar = GTK_PROGRESS_BAR(widget);
1450           XpThemeElement xp_progress_bar = map_gtk_progress_bar_to_xp (progress_bar, TRUE);
1451           if (xp_theme_draw (window, xp_progress_bar,
1452                              style, x, y, width, height, state_type, area))
1453             {
1454               return;
1455             }
1456           else
1457             {
1458               /* Blank in classic Windows */
1459             }
1460         }
1461       else if (widget && GTK_IS_SCROLLBAR(widget))
1462         {
1463           gboolean is_vertical = GTK_IS_VSCROLLBAR(widget);
1464
1465           if (GTK_IS_RANGE(widget)
1466               && xp_theme_draw(window,
1467                                is_vertical
1468                                ? XP_THEME_ELEMENT_TROUGH_V
1469                                : XP_THEME_ELEMENT_TROUGH_H,
1470                                style,
1471                                x, y, width, height, state_type, area))
1472             {
1473               return;
1474             }
1475           else
1476             {
1477               GdkGCValues gc_values;
1478               GdkGC *gc;
1479               GdkPixmap *pixmap;
1480
1481               sanitize_size (window, &width, &height);
1482
1483               pixmap = gdk_pixmap_new (window, 2, 2, -1);
1484
1485               gdk_draw_point (pixmap, style->bg_gc[GTK_STATE_NORMAL], 0, 0);
1486               gdk_draw_point (pixmap, style->bg_gc[GTK_STATE_NORMAL], 1, 1);
1487               gdk_draw_point (pixmap, style->light_gc[GTK_STATE_NORMAL], 1, 0);
1488               gdk_draw_point (pixmap, style->light_gc[GTK_STATE_NORMAL], 0, 1);
1489
1490               gc_values.fill = GDK_TILED;
1491               gc_values.tile = pixmap;
1492               gc_values.ts_x_origin = x;
1493               gc_values.ts_y_origin = y;
1494               gc = gdk_gc_new_with_values (window, &gc_values,
1495                                            GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN | GDK_GC_FILL | GDK_GC_TILE);
1496
1497               if (area)
1498                 gdk_gc_set_clip_rectangle (gc, area);
1499
1500               gdk_draw_rectangle (window, gc, TRUE, x, y, width, height);
1501
1502               gdk_gc_unref (gc);
1503               gdk_drawable_unref (pixmap);
1504
1505               return;
1506             }
1507         }
1508       else if (widget && GTK_IS_SCALE(widget))
1509         {
1510           gboolean is_vertical = GTK_IS_VSCALE(widget);
1511
1512           parent_class->draw_box (style, window, state_type, GTK_SHADOW_NONE, area,
1513                                   widget, detail, x, y, width, height);
1514
1515           if(is_vertical)
1516             parent_class->draw_box(style, window, state_type, GTK_SHADOW_ETCHED_IN, area, NULL, NULL, (2 * x + width)/2, y, 1, height);
1517           else
1518             parent_class->draw_box(style, window, state_type, GTK_SHADOW_ETCHED_IN, area, NULL, NULL, x, (2 * y + height)/2, width, 1);
1519
1520           return;
1521         }
1522     }
1523   else if (detail && strcmp (detail, "optionmenu") == 0)
1524     {
1525       if (xp_theme_draw(window, XP_THEME_ELEMENT_EDIT_TEXT,
1526                         style, x, y, width, height, state_type, area))
1527         {
1528           return;
1529         }
1530     }
1531   else if (detail && (strcmp (detail, "vscrollbar") == 0 || strcmp (detail, "hscrollbar") == 0))
1532   {
1533        GtkScrollbar * scrollbar = GTK_SCROLLBAR(widget);
1534           if (shadow_type == GTK_SHADOW_IN)
1535                 shadow_type = GTK_SHADOW_ETCHED_IN;
1536        if (scrollbar->range.adjustment->page_size >= (scrollbar->range.adjustment->upper-scrollbar->range.adjustment->lower))
1537            shadow_type = GTK_SHADOW_OUT;
1538   }
1539   else
1540   {
1541          const gchar * name = gtk_widget_get_name (widget);
1542
1543           if (name && !strcmp (name, "gtk-tooltips")) {
1544          if (xp_theme_draw (window, XP_THEME_ELEMENT_TOOLTIP, style, x, y, width, height, state_type, area))
1545            {
1546                         return;
1547             }
1548                 }
1549   }
1550
1551   parent_class->draw_box (style, window, state_type, shadow_type, area,
1552                           widget, detail, x, y, width, height);
1553
1554   if (detail && strcmp (detail, "optionmenu") == 0)
1555     {
1556       GtkRequisition indicator_size;
1557       GtkBorder indicator_spacing;
1558       gint vline_x;
1559
1560       option_menu_get_props (widget, &indicator_size, &indicator_spacing);
1561
1562       sanitize_size (window, &width, &height);
1563
1564       if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
1565         vline_x = x + indicator_size.width + indicator_spacing.left + indicator_spacing.right;
1566       else
1567         vline_x = x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness;
1568
1569       parent_class->draw_vline (style, window, state_type, area, widget,
1570                                 detail,
1571                                 y + style->ythickness + 1,
1572                                 y + height - style->ythickness - 3,
1573                                 vline_x);
1574     }
1575 }
1576
1577 static void
1578 draw_tab (GtkStyle      *style,
1579           GdkWindow     *window,
1580           GtkStateType   state,
1581           GtkShadowType  shadow,
1582           GdkRectangle  *area,
1583           GtkWidget     *widget,
1584           const gchar   *detail,
1585           gint           x,
1586           gint           y,
1587           gint           width,
1588           gint           height)
1589 {
1590   GtkRequisition indicator_size;
1591   GtkBorder indicator_spacing;
1592
1593   gint arrow_height;
1594
1595   g_return_if_fail (style != NULL);
1596   g_return_if_fail (window != NULL);
1597
1598   if (detail && ! strcmp (detail, "optionmenutab"))
1599     {
1600       if (xp_theme_draw(window, XP_THEME_ELEMENT_COMBOBUTTON,
1601                         style, x-5, widget->allocation.y+1,
1602                         width+10, widget->allocation.height-2, state, area))
1603         {
1604           return;
1605         }
1606     }
1607
1608   if (widget)
1609     gtk_widget_style_get (widget, "indicator_size", &indicator_size, NULL);
1610
1611   option_menu_get_props (widget, &indicator_size, &indicator_spacing);
1612
1613   x += (width - indicator_size.width) / 2;
1614   arrow_height = (indicator_size.width + 1) / 2;
1615
1616   y += (height - arrow_height) / 2;
1617
1618   draw_varrow (window, style->black_gc, shadow, area, GTK_ARROW_DOWN,
1619                x, y, indicator_size.width, arrow_height);
1620 }
1621
1622 /* this is an undefined magic value that, according to the mozilla folks,
1623    worked for all the various themes that they tried */
1624 #define XP_EDGE_SIZE 2
1625
1626 static void
1627 draw_extension(GtkStyle *style,
1628                GdkWindow *window,
1629                GtkStateType state_type,
1630                GtkShadowType shadow_type,
1631                GdkRectangle *area,
1632                GtkWidget *widget,
1633                const gchar *detail,
1634                gint x,
1635                gint y,
1636                gint width,
1637                gint height,
1638                GtkPositionType gap_side)
1639 {
1640   if (detail && !strcmp(detail, "tab"))
1641     {
1642       GtkNotebook *notebook = GTK_NOTEBOOK(widget);
1643       GtkPositionType pos_type = gtk_notebook_get_tab_pos(notebook);
1644
1645       if (pos_type == GTK_POS_TOP && state_type == GTK_STATE_NORMAL)
1646           height += XP_EDGE_SIZE;
1647
1648 #if 0
1649       /* FIXME: pos != TOP to be implemented */
1650       else if (pos_type == GTK_POS_BOTTOM)
1651         y -= XP_EDGE_SIZE;
1652       else if (pos_type == GTK_POS_RIGHT)
1653         width += XP_EDGE_SIZE;
1654       else if (pos_type == GTK_POS_LEFT)
1655         height -= XP_EDGE_SIZE;
1656 #endif
1657
1658       if (pos_type == GTK_POS_TOP
1659           && xp_theme_draw
1660           (window, gtk_notebook_get_current_page(notebook)==0
1661            ? XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE
1662            : XP_THEME_ELEMENT_TAB_ITEM,
1663            style, x, y, width, height, state_type, area))
1664         {
1665           return;
1666         }
1667     }
1668   parent_class->draw_extension
1669     (style, window, state_type, shadow_type, area, widget, detail,
1670          x, y, width, height, gap_side);
1671 }
1672
1673 static void
1674 draw_box_gap (GtkStyle *style, GdkWindow *window, GtkStateType state_type,
1675               GtkShadowType shadow_type, GdkRectangle *area,
1676               GtkWidget *widget, const gchar *detail, gint x,
1677               gint y, gint width, gint height, GtkPositionType gap_side,
1678               gint gap_x, gint gap_width)
1679 {
1680   if (detail && !strcmp(detail, "notebook"))
1681     {
1682       GtkNotebook *notebook = GTK_NOTEBOOK(widget);
1683
1684       /* FIXME: pos != TOP to be implemented */
1685       if (gtk_notebook_get_tab_pos(notebook) == GTK_POS_TOP && xp_theme_draw(window, XP_THEME_ELEMENT_TAB_PANE, style,  x, y, width, height,
1686                         state_type, area))
1687         {
1688           return;
1689         }
1690     }
1691   parent_class->draw_box_gap(style, window, state_type, shadow_type,
1692                              area, widget, detail, x, y, width, height,
1693                              gap_side, gap_x, gap_width);
1694 }
1695
1696 static void
1697 draw_flat_box (GtkStyle *style, GdkWindow *window,
1698                GtkStateType state_type, GtkShadowType shadow_type,
1699                GdkRectangle *area, GtkWidget *widget,
1700                const gchar *detail, gint x, gint y,
1701                gint width, gint height)
1702 {
1703   if (detail && ! strcmp (detail, "checkbutton"))
1704     {
1705       if (state_type == GTK_STATE_PRELIGHT)
1706         {
1707           return;
1708         }
1709     }
1710
1711   parent_class->draw_flat_box(style, window, state_type, shadow_type,
1712                               area, widget, detail, x, y, width, height);
1713 }
1714
1715 static void
1716 draw_shadow (GtkStyle      *style,
1717              GdkWindow     *window,
1718              GtkStateType   state_type,
1719              GtkShadowType  shadow_type,
1720              GdkRectangle  *area,
1721              GtkWidget     *widget,
1722              const gchar   *detail,
1723              gint           x,
1724              gint           y,
1725              gint           width,
1726              gint           height)
1727 {
1728   if(detail && ! strcmp(detail, "entry"))
1729     {
1730       if (xp_theme_draw(window, XP_THEME_ELEMENT_EDIT_TEXT, style,
1731                         x, y, width, height, state_type, area))
1732         {
1733           return;
1734         }
1735     }
1736   parent_class->draw_shadow (style, window, state_type, shadow_type, area, widget,
1737                              detail, x, y, width, height);
1738 }
1739
1740 static void
1741 draw_hline (GtkStyle            *style,
1742             GdkWindow           *window,
1743             GtkStateType         state_type,
1744             GdkRectangle        *area,
1745             GtkWidget           *widget,
1746             const gchar         *detail,
1747             gint                 x1,
1748             gint                 x2,
1749             gint                 y)
1750 {
1751
1752   if (detail && !strcmp(detail, "menuitem")) {
1753           if (xp_theme_draw(window, XP_THEME_ELEMENT_MENU_SEPARATOR, style,
1754                         x1, y, x2, style->ythickness, state_type, area)) {
1755                         return;
1756           }
1757   }
1758
1759   parent_class->draw_hline (style, window, state_type, area, widget,
1760                             detail, x1, x2, y);
1761 }
1762
1763 static void
1764 draw_vline (GtkStyle            *style,
1765             GdkWindow           *window,
1766             GtkStateType         state_type,
1767             GdkRectangle        *area,
1768             GtkWidget           *widget,
1769             const gchar         *detail,
1770             gint                 y1,
1771             gint                 y2,
1772             gint                 x)
1773 {
1774   parent_class->draw_vline (style, window, state_type, area, widget,
1775                             detail, y1, y2, x);
1776 }
1777
1778 static void
1779 draw_resize_grip (GtkStyle      *style,
1780                        GdkWindow     *window,
1781                        GtkStateType   state_type,
1782                        GdkRectangle  *area,
1783                        GtkWidget     *widget,
1784                        const gchar   *detail,
1785                        GdkWindowEdge  edge,
1786                        gint           x,
1787                        gint           y,
1788                        gint           width,
1789                        gint           height)
1790 {
1791         if (detail && !strcmp(detail, "statusbar")) {
1792                 if (!xp_theme_draw(window, XP_THEME_ELEMENT_STATUS_GRIPPER, style, x, y, width, height,
1793                            state_type, area))
1794                         return;
1795         }
1796
1797         parent_class->draw_resize_grip (style, window, state_type, area,
1798                                                                         widget, detail, edge, x, y, width, height);
1799 }
1800
1801 static void
1802 draw_handle (GtkStyle        *style,
1803              GdkWindow       *window,
1804              GtkStateType     state_type,
1805              GtkShadowType    shadow_type,
1806              GdkRectangle    *area,
1807              GtkWidget       *widget,
1808              const gchar     *detail,
1809              gint             x,
1810              gint             y,
1811              gint             width,
1812              gint             height,
1813              GtkOrientation   orientation)
1814 {
1815   if (GTK_IS_HANDLE_BOX (widget))
1816     {
1817       XpThemeElement hndl;
1818
1819       sanitize_size (window, &width, &height);
1820
1821       if (orientation == GTK_ORIENTATION_VERTICAL)
1822         hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_V;
1823       else
1824         hndl = XP_THEME_ELEMENT_REBAR_GRIPPER_H;
1825
1826       if (xp_theme_draw (window, hndl, style, x, y, width, height,
1827                          state_type, area))
1828         {
1829           return;
1830         }
1831
1832       /* grippers are just flat boxes when they're not a toolbar */
1833       parent_class->draw_box (style, window, state_type, shadow_type,
1834                               area, widget, detail, x, y, width, height);
1835     }
1836   else if (!GTK_IS_PANED (widget))
1837     {
1838       /* TODO: Draw handle boxes as double lines: || */
1839       parent_class->draw_handle (style, window, state_type, shadow_type,
1840                                  area, widget, detail, x, y, width, height,
1841                                  orientation);
1842     }
1843 }
1844
1845 static void
1846 msw_style_init_from_rc (GtkStyle * style, GtkRcStyle * rc_style)
1847 {
1848   setup_system_font (style);
1849   setup_menu_settings (gtk_settings_get_default ());
1850   setup_system_styles (style);
1851   parent_class->init_from_rc(style, rc_style);
1852 }
1853
1854 static void
1855 msw_style_class_init (MswStyleClass *klass)
1856 {
1857   GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
1858
1859   parent_class = g_type_class_peek_parent (klass);
1860
1861   style_class->init_from_rc = msw_style_init_from_rc;
1862   style_class->draw_arrow = draw_arrow;
1863   style_class->draw_box = draw_box;
1864   style_class->draw_check = draw_check;
1865   style_class->draw_option = draw_option;
1866   style_class->draw_tab = draw_tab;
1867   style_class->draw_flat_box = draw_flat_box;
1868   style_class->draw_expander = draw_expander;
1869   style_class->draw_extension = draw_extension;
1870   style_class->draw_box_gap = draw_box_gap;
1871   style_class->draw_shadow = draw_shadow;
1872   style_class->draw_hline = draw_hline;
1873   style_class->draw_vline = draw_vline;
1874   style_class->draw_handle = draw_handle;
1875   style_class->draw_resize_grip = draw_resize_grip;
1876 }
1877
1878 GType msw_type_style = 0;
1879
1880 void
1881 msw_style_register_type (GTypeModule *module)
1882 {
1883   static const GTypeInfo object_info =
1884   {
1885     sizeof (MswStyleClass),
1886     (GBaseInitFunc) NULL,
1887     (GBaseFinalizeFunc) NULL,
1888     (GClassInitFunc) msw_style_class_init,
1889     NULL,           /* class_finalize */
1890     NULL,           /* class_data */
1891     sizeof (MswStyle),
1892     0,              /* n_preallocs */
1893     (GInstanceInitFunc) NULL,
1894   };
1895
1896   msw_type_style = g_type_module_register_type (module,
1897                                                    GTK_TYPE_STYLE,
1898                                                    "MswStyle",
1899                                                    &object_info, 0);
1900 }
1901
1902 void
1903 msw_style_init (void)
1904 {
1905   xp_theme_init ();
1906   msw_style_setup_system_settings ();
1907   setup_msw_rc_style ();
1908 }