]> Pileus Git - ~andy/gtk/blob - modules/engines/ms-windows/xp_theme.c
Include "config.h" instead of <config.h> Command used: find -name
[~andy/gtk] / modules / engines / ms-windows / xp_theme.c
1 /* MS-Windows Engine (aka GTK-Wimp)
2  *
3  * Copyright (C) 2003, 2004 Raymond Penners <raymond@dotsphinx.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #define _WIN32_WINNT 0x0501
22
23 #include "xp_theme.h"
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <windows.h>
30 #include <math.h>
31 #include <string.h>
32 #include <stdio.h>
33
34 /* #include "gdk/gdkwin32.h" */
35 #include "gdk/win32/gdkwin32.h"
36
37 #include "xp_theme_defs.h"
38
39 #ifndef TMT_CAPTIONFONT
40
41 /* These aren't in mingw's "w32api" headers, nor in the Platform SDK
42  * headers.
43  */
44 #define TMT_CAPTIONFONT   801
45 #define TMT_MENUFONT      803
46 #define TMT_STATUSFONT    804
47 #define TMT_MSGBOXFONT    805
48 #endif
49
50 #define GP_LINEHORZ       2
51 #define GP_LINEVERT       3
52 #define TP_SEPARATOR      5
53 #define TP_SEPARATORVERT  6
54
55 /* GLOBALS LINEHORZ states */
56 #define LHS_FLAT          1
57 #define LHS_RAISED        2
58 #define LHS_SUNKEN        3
59
60 /* GLOBAL LINEVERT states */
61 #define LVS_FLAT          1
62 #define LVS_RAISED        2
63 #define LVS_SUNKEN        3
64
65 /* TRACKBAR parts */
66 #define TKP_TRACK         1
67 #define TKP_TRACKVERT     2
68 #define TKP_THUMB         3
69 #define TKP_THUMBBOTTOM   4
70 #define TKP_THUMBTOP      5
71 #define TKP_THUMBVERT     6
72 #define TKP_THUMBLEFT     7
73 #define TKP_THUMBRIGHT    8
74 #define TKP_TICS          9
75 #define TKP_TICSVERT      10
76
77 #define TRS_NORMAL        1
78
79 static const LPCWSTR class_descriptors[] = {
80   L"Scrollbar",                 /* XP_THEME_CLASS_SCROLLBAR */
81   L"Button",                    /* XP_THEME_CLASS_BUTTON */
82   L"Header",                    /* XP_THEME_CLASS_HEADER */
83   L"ComboBox",                  /* XP_THEME_CLASS_COMBOBOX */
84   L"Tab",                       /* XP_THEME_CLASS_TAB */
85   L"Edit",                      /* XP_THEME_CLASS_EDIT */
86   L"TreeView",                  /* XP_THEME_CLASS_TREEVIEW */
87   L"Spin",                      /* XP_THEME_CLASS_SPIN */
88   L"Progress",                  /* XP_THEME_CLASS_PROGRESS */
89   L"Tooltip",                   /* XP_THEME_CLASS_TOOLTIP */
90   L"Rebar",                     /* XP_THEME_CLASS_REBAR */
91   L"Toolbar",                   /* XP_THEME_CLASS_TOOLBAR */
92   L"Globals",                   /* XP_THEME_CLASS_GLOBALS */
93   L"Menu",                      /* XP_THEME_CLASS_MENU */
94   L"Window",                    /* XP_THEME_CLASS_WINDOW */
95   L"Status",                    /* XP_THEME_CLASS_STATUS */
96   L"Trackbar"                   /* XP_THEME_CLASS_TRACKBAR */
97 };
98
99 static const short element_part_map[XP_THEME_ELEMENT__SIZEOF] = {
100   BP_CHECKBOX,
101   BP_CHECKBOX,
102   BP_CHECKBOX,
103   BP_PUSHBUTTON,
104   HP_HEADERITEM,
105   CP_DROPDOWNBUTTON,
106   TABP_BODY,
107   TABP_TABITEM,
108   TABP_TABITEMLEFTEDGE,
109   TABP_TABITEMRIGHTEDGE,
110   TABP_PANE,
111   SBP_THUMBBTNHORZ,
112   SBP_THUMBBTNVERT,
113   SBP_ARROWBTN,
114   SBP_ARROWBTN,
115   SBP_ARROWBTN,
116   SBP_ARROWBTN,
117   SBP_GRIPPERHORZ,
118   SBP_GRIPPERVERT,
119   SBP_LOWERTRACKHORZ,
120   SBP_LOWERTRACKVERT,
121   EP_EDITTEXT,
122   BP_PUSHBUTTON,
123   SPNP_UP,
124   SPNP_DOWN,
125   BP_RADIOBUTTON,
126   BP_RADIOBUTTON,
127   TVP_GLYPH,
128   TVP_GLYPH,
129   PP_CHUNK,
130   PP_CHUNKVERT,
131   PP_BAR,
132   PP_BARVERT,
133   TTP_STANDARD,
134   0 /* RP_BAND */ ,
135   RP_GRIPPER,
136   RP_GRIPPERVERT,
137   RP_CHEVRON,
138   TP_BUTTON,
139   MP_MENUITEM,
140   MP_SEPARATOR,
141   SP_GRIPPER,
142   SP_PANE,
143   GP_LINEHORZ,
144   GP_LINEVERT,
145   TP_SEPARATOR,
146   TP_SEPARATORVERT,
147   TKP_TRACK,
148   TKP_TRACKVERT,
149   TKP_THUMB,
150   TKP_THUMBVERT,
151   TKP_TICS,
152   TKP_TICSVERT
153 };
154
155 static HINSTANCE uxtheme_dll = NULL;
156 static HTHEME open_themes[XP_THEME_CLASS__SIZEOF];
157 static gboolean use_xp_theme = FALSE;
158
159 typedef HRESULT (FAR PASCAL *GetThemeSysFontFunc)           (HTHEME hTheme, int iFontID, OUT LOGFONT *plf);
160 typedef int (FAR PASCAL *GetThemeSysSizeFunc)               (HTHEME hTheme, int iSizeId);
161 typedef COLORREF (FAR PASCAL *GetThemeSysColorFunc)         (HTHEME hTheme,
162                                                              int iColorID);
163 typedef HTHEME (FAR PASCAL *OpenThemeDataFunc)              (HWND hwnd,
164                                                              LPCWSTR pszClassList);
165 typedef HRESULT (FAR PASCAL *CloseThemeDataFunc)            (HTHEME theme);
166 typedef HRESULT (FAR PASCAL *DrawThemeBackgroundFunc)       (HTHEME hTheme, HDC hdc, int iPartId, int iStateId,
167                                                              const RECT *pRect, const RECT *pClipRect);
168 typedef HRESULT (FAR PASCAL *EnableThemeDialogTextureFunc)  (HWND hwnd,
169                                                              DWORD dwFlags);
170 typedef BOOL (FAR PASCAL *IsThemeActiveFunc)                (VOID);
171 typedef BOOL (FAR PASCAL *IsAppThemedFunc)                  (VOID);
172 typedef BOOL (FAR PASCAL *IsThemeBackgroundPartiallyTransparentFunc) (HTHEME hTheme,
173                                                                       int iPartId,
174                                                                       int iStateId);
175 typedef HRESULT (FAR PASCAL *DrawThemeParentBackgroundFunc) (HWND hwnd,
176                                                              HDC hdc,
177                                                              RECT *prc);
178
179 static GetThemeSysFontFunc get_theme_sys_font_func = NULL;
180 static GetThemeSysColorFunc get_theme_sys_color_func = NULL;
181 static GetThemeSysSizeFunc get_theme_sys_metric_func = NULL;
182 static OpenThemeDataFunc open_theme_data_func = NULL;
183 static CloseThemeDataFunc close_theme_data_func = NULL;
184 static DrawThemeBackgroundFunc draw_theme_background_func = NULL;
185 static EnableThemeDialogTextureFunc enable_theme_dialog_texture_func = NULL;
186 static IsThemeActiveFunc is_theme_active_func = NULL;
187 static IsAppThemedFunc is_app_themed_func = NULL;
188 static IsThemeBackgroundPartiallyTransparentFunc is_theme_partially_transparent_func = NULL;
189 static DrawThemeParentBackgroundFunc draw_theme_parent_background_func = NULL;
190
191 static void
192 xp_theme_close_open_handles (void)
193 {
194   int i;
195
196   for (i = 0; i < XP_THEME_CLASS__SIZEOF; i++)
197     {
198       if (open_themes[i])
199         {
200           close_theme_data_func (open_themes[i]);
201           open_themes[i] = NULL;
202         }
203     }
204 }
205
206 void
207 xp_theme_init (void)
208 {
209   if (uxtheme_dll)
210     return;
211
212   memset (open_themes, 0, sizeof (open_themes));
213
214   uxtheme_dll = LoadLibrary ("uxtheme.dll");
215   if (!uxtheme_dll)
216     return;
217
218   is_app_themed_func = (IsAppThemedFunc) GetProcAddress (uxtheme_dll, "IsAppThemed");
219
220   if (is_app_themed_func)
221     {
222       is_theme_active_func = (IsThemeActiveFunc) GetProcAddress (uxtheme_dll, "IsThemeActive");
223       open_theme_data_func = (OpenThemeDataFunc) GetProcAddress (uxtheme_dll, "OpenThemeData");
224       close_theme_data_func = (CloseThemeDataFunc) GetProcAddress (uxtheme_dll, "CloseThemeData");
225       draw_theme_background_func = (DrawThemeBackgroundFunc) GetProcAddress (uxtheme_dll, "DrawThemeBackground");
226       enable_theme_dialog_texture_func = (EnableThemeDialogTextureFunc) GetProcAddress (uxtheme_dll, "EnableThemeDialogTexture");
227       get_theme_sys_font_func = (GetThemeSysFontFunc) GetProcAddress (uxtheme_dll, "GetThemeSysFont");
228       get_theme_sys_color_func = (GetThemeSysColorFunc) GetProcAddress (uxtheme_dll, "GetThemeSysColor");
229       get_theme_sys_metric_func = (GetThemeSysSizeFunc) GetProcAddress (uxtheme_dll, "GetThemeSysSize");
230       is_theme_partially_transparent_func = (IsThemeBackgroundPartiallyTransparentFunc) GetProcAddress (uxtheme_dll, "IsThemeBackgroundPartiallyTransparent");
231       draw_theme_parent_background_func = (DrawThemeParentBackgroundFunc) GetProcAddress (uxtheme_dll, "DrawThemeParentBackground");
232     }
233
234   if (is_app_themed_func && is_theme_active_func)
235     {
236       use_xp_theme = (is_app_themed_func () && is_theme_active_func ());
237     }
238   else
239     {
240       use_xp_theme = FALSE;
241     }
242 }
243
244 void
245 xp_theme_reset (void)
246 {
247   xp_theme_close_open_handles ();
248
249   if (is_app_themed_func && is_theme_active_func)
250     {
251       use_xp_theme = (is_app_themed_func () && is_theme_active_func ());
252     }
253   else
254     {
255       use_xp_theme = FALSE;
256     }
257 }
258
259 void
260 xp_theme_exit (void)
261 {
262   if (!uxtheme_dll)
263     return;
264
265   xp_theme_close_open_handles ();
266
267   FreeLibrary (uxtheme_dll);
268   uxtheme_dll = NULL;
269   use_xp_theme = FALSE;
270
271   is_app_themed_func = NULL;
272   is_theme_active_func = NULL;
273   open_theme_data_func = NULL;
274   close_theme_data_func = NULL;
275   draw_theme_background_func = NULL;
276   enable_theme_dialog_texture_func = NULL;
277   get_theme_sys_font_func = NULL;
278   get_theme_sys_color_func = NULL;
279   get_theme_sys_metric_func = NULL;
280   is_theme_partially_transparent_func = NULL;
281   draw_theme_parent_background_func = NULL;
282 }
283
284 static HTHEME
285 xp_theme_get_handle_by_class (XpThemeClass klazz)
286 {
287   if (!open_themes[klazz] && open_theme_data_func)
288     {
289       open_themes[klazz] = open_theme_data_func (NULL, class_descriptors[klazz]);
290     }
291
292   return open_themes[klazz];
293 }
294
295 static HTHEME
296 xp_theme_get_handle_by_element (XpThemeElement element)
297 {
298   HTHEME ret = NULL;
299   XpThemeClass klazz = XP_THEME_CLASS__SIZEOF;
300
301   switch (element)
302     {
303     case XP_THEME_ELEMENT_TOOLTIP:
304       klazz = XP_THEME_CLASS_TOOLTIP;
305       break;
306
307     case XP_THEME_ELEMENT_REBAR:
308     case XP_THEME_ELEMENT_REBAR_GRIPPER_H:
309     case XP_THEME_ELEMENT_REBAR_GRIPPER_V:
310     case XP_THEME_ELEMENT_REBAR_CHEVRON:
311       klazz = XP_THEME_CLASS_REBAR;
312       break;
313
314     case XP_THEME_ELEMENT_SCALE_TROUGH_H:
315     case XP_THEME_ELEMENT_SCALE_TROUGH_V:
316     case XP_THEME_ELEMENT_SCALE_SLIDER_H:
317     case XP_THEME_ELEMENT_SCALE_SLIDER_V:
318     case XP_THEME_ELEMENT_SCALE_TICS_H:
319     case XP_THEME_ELEMENT_SCALE_TICS_V:
320       klazz = XP_THEME_CLASS_TRACKBAR;
321       break;
322
323     case XP_THEME_ELEMENT_STATUS_GRIPPER:
324     case XP_THEME_ELEMENT_STATUS_PANE:
325       klazz = XP_THEME_CLASS_STATUS;
326       break;
327
328     case XP_THEME_ELEMENT_TOOLBAR_BUTTON:
329     case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_H:
330     case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_V:
331       klazz = XP_THEME_CLASS_TOOLBAR;
332       break;
333
334     case XP_THEME_ELEMENT_MENU_ITEM:
335     case XP_THEME_ELEMENT_MENU_SEPARATOR:
336       klazz = XP_THEME_CLASS_MENU;
337       break;
338
339     case XP_THEME_ELEMENT_PRESSED_CHECKBOX:
340     case XP_THEME_ELEMENT_INCONSISTENT_CHECKBOX:
341     case XP_THEME_ELEMENT_CHECKBOX:
342     case XP_THEME_ELEMENT_BUTTON:
343     case XP_THEME_ELEMENT_DEFAULT_BUTTON:
344     case XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON:
345     case XP_THEME_ELEMENT_RADIO_BUTTON:
346       klazz = XP_THEME_CLASS_BUTTON;
347       break;
348
349     case XP_THEME_ELEMENT_LIST_HEADER:
350       klazz = XP_THEME_CLASS_HEADER;
351       break;
352
353     case XP_THEME_ELEMENT_COMBOBUTTON:
354       klazz = XP_THEME_CLASS_COMBOBOX;
355       break;
356
357     case XP_THEME_ELEMENT_BODY:
358     case XP_THEME_ELEMENT_TAB_ITEM:
359     case XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE:
360     case XP_THEME_ELEMENT_TAB_ITEM_RIGHT_EDGE:
361     case XP_THEME_ELEMENT_TAB_PANE:
362       klazz = XP_THEME_CLASS_TAB;
363       break;
364
365     case XP_THEME_ELEMENT_SCROLLBAR_V:
366     case XP_THEME_ELEMENT_SCROLLBAR_H:
367     case XP_THEME_ELEMENT_ARROW_UP:
368     case XP_THEME_ELEMENT_ARROW_DOWN:
369     case XP_THEME_ELEMENT_ARROW_LEFT:
370     case XP_THEME_ELEMENT_ARROW_RIGHT:
371     case XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V:
372     case XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H:
373     case XP_THEME_ELEMENT_TROUGH_V:
374     case XP_THEME_ELEMENT_TROUGH_H:
375       klazz = XP_THEME_CLASS_SCROLLBAR;
376       break;
377
378     case XP_THEME_ELEMENT_EDIT_TEXT:
379       klazz = XP_THEME_CLASS_EDIT;
380       break;
381
382     case XP_THEME_ELEMENT_SPIN_BUTTON_UP:
383     case XP_THEME_ELEMENT_SPIN_BUTTON_DOWN:
384       klazz = XP_THEME_CLASS_SPIN;
385       break;
386
387     case XP_THEME_ELEMENT_PROGRESS_BAR_H:
388     case XP_THEME_ELEMENT_PROGRESS_BAR_V:
389     case XP_THEME_ELEMENT_PROGRESS_TROUGH_H:
390     case XP_THEME_ELEMENT_PROGRESS_TROUGH_V:
391       klazz = XP_THEME_CLASS_PROGRESS;
392       break;
393
394     case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED:
395     case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED:
396       klazz = XP_THEME_CLASS_TREEVIEW;
397       break;
398
399     case XP_THEME_ELEMENT_LINE_H:
400     case XP_THEME_ELEMENT_LINE_V:
401       klazz = XP_THEME_CLASS_GLOBALS;
402       break;
403
404     default:
405       break;
406     }
407
408   if (klazz != XP_THEME_CLASS__SIZEOF)
409     {
410       ret = xp_theme_get_handle_by_class (klazz);
411     }
412
413   return ret;
414 }
415
416 static int
417 xp_theme_map_gtk_state (XpThemeElement element, GtkStateType state)
418 {
419   int ret = 0;
420
421   switch (element)
422     {
423     case XP_THEME_ELEMENT_TOOLTIP:
424       ret = TTSS_NORMAL;
425       break;
426
427     case XP_THEME_ELEMENT_REBAR:
428       ret = 0;
429       break;
430
431     case XP_THEME_ELEMENT_REBAR_GRIPPER_H:
432     case XP_THEME_ELEMENT_REBAR_GRIPPER_V:
433       ret = 0;
434       break;
435
436     case XP_THEME_ELEMENT_STATUS_GRIPPER:
437     case XP_THEME_ELEMENT_STATUS_PANE:
438       ret = 1;
439       break;
440
441     case XP_THEME_ELEMENT_REBAR_CHEVRON:
442       switch (state)
443         {
444         case GTK_STATE_PRELIGHT:
445           ret = CHEVS_HOT;
446           break;
447
448         case GTK_STATE_SELECTED:
449         case GTK_STATE_ACTIVE:
450           ret = CHEVS_PRESSED;
451           break;
452
453         default:
454           ret = CHEVS_NORMAL;
455         }
456       break;
457
458     case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_H:
459     case XP_THEME_ELEMENT_TOOLBAR_SEPARATOR_V:
460       ret = TS_NORMAL;
461       break;
462
463     case XP_THEME_ELEMENT_TOOLBAR_BUTTON:
464       switch (state)
465         {
466         case GTK_STATE_ACTIVE:
467           ret = TS_PRESSED;
468           break;
469
470         case GTK_STATE_PRELIGHT:
471           ret = TS_HOT;
472           break;
473
474         case GTK_STATE_INSENSITIVE:
475           ret = TS_DISABLED;
476           break;
477
478         default:
479           ret = TS_NORMAL;
480         }
481       break;
482
483     case XP_THEME_ELEMENT_TAB_PANE:
484       ret = 1;
485       break;
486
487     case XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE:
488     case XP_THEME_ELEMENT_TAB_ITEM_RIGHT_EDGE:
489     case XP_THEME_ELEMENT_TAB_ITEM:
490       switch (state)
491         {
492         case GTK_STATE_PRELIGHT:
493           ret = TIS_HOT;
494           break;
495
496         case GTK_STATE_INSENSITIVE:
497           ret = TIS_DISABLED;
498           break;
499
500         case GTK_STATE_SELECTED:
501         case GTK_STATE_ACTIVE:
502           ret = TIS_NORMAL;
503           break;
504
505         default:
506           ret = TIS_SELECTED;
507         }
508       break;
509
510     case XP_THEME_ELEMENT_EDIT_TEXT:
511       switch (state)
512         {
513         case GTK_STATE_PRELIGHT:
514           ret = ETS_FOCUSED;
515           break;
516
517         case GTK_STATE_INSENSITIVE:
518           ret = ETS_READONLY;
519           break;
520
521         case GTK_STATE_SELECTED:
522         case GTK_STATE_ACTIVE:
523         default:
524           ret = ETS_NORMAL;
525         }
526       break;
527
528     case XP_THEME_ELEMENT_TROUGH_H:
529     case XP_THEME_ELEMENT_TROUGH_V:
530       ret = SCRBS_NORMAL;
531       break;
532
533     case XP_THEME_ELEMENT_SCROLLBAR_H:
534     case XP_THEME_ELEMENT_SCROLLBAR_V:
535       switch (state)
536         {
537         case GTK_STATE_SELECTED:
538         case GTK_STATE_ACTIVE:
539           ret = SCRBS_PRESSED;
540           break;
541
542         case GTK_STATE_PRELIGHT:
543           ret = SCRBS_HOT;
544           break;
545
546         case GTK_STATE_INSENSITIVE:
547           ret = SCRBS_DISABLED;
548           break;
549
550         default:
551           ret = SCRBS_NORMAL;
552         }
553       break;
554
555     case XP_THEME_ELEMENT_ARROW_DOWN:
556       switch (state)
557         {
558         case GTK_STATE_ACTIVE:
559           ret = ABS_DOWNPRESSED;
560           break;
561
562         case GTK_STATE_PRELIGHT:
563           ret = ABS_DOWNHOT;
564           break;
565
566         case GTK_STATE_INSENSITIVE:
567           ret = ABS_DOWNDISABLED;
568           break;
569
570         default:
571           ret = ABS_DOWNNORMAL;
572         }
573       break;
574
575     case XP_THEME_ELEMENT_ARROW_UP:
576       switch (state)
577         {
578         case GTK_STATE_ACTIVE:
579           ret = ABS_UPPRESSED;
580           break;
581
582         case GTK_STATE_PRELIGHT:
583           ret = ABS_UPHOT;
584           break;
585
586         case GTK_STATE_INSENSITIVE:
587           ret = ABS_UPDISABLED;
588           break;
589
590         default:
591           ret = ABS_UPNORMAL;
592         }
593       break;
594
595     case XP_THEME_ELEMENT_ARROW_LEFT:
596       switch (state)
597         {
598         case GTK_STATE_ACTIVE:
599           ret = ABS_LEFTPRESSED;
600           break;
601
602         case GTK_STATE_PRELIGHT:
603           ret = ABS_LEFTHOT;
604           break;
605
606         case GTK_STATE_INSENSITIVE:
607           ret = ABS_LEFTDISABLED;
608           break;
609
610         default:
611           ret = ABS_LEFTNORMAL;
612         }
613       break;
614
615     case XP_THEME_ELEMENT_ARROW_RIGHT:
616       switch (state)
617         {
618         case GTK_STATE_ACTIVE:
619           ret = ABS_RIGHTPRESSED;
620           break;
621
622         case GTK_STATE_PRELIGHT:
623           ret = ABS_RIGHTHOT;
624           break;
625
626         case GTK_STATE_INSENSITIVE:
627           ret = ABS_RIGHTDISABLED;
628           break;
629
630         default:
631           ret = ABS_RIGHTNORMAL;
632         }
633       break;
634
635     case XP_THEME_ELEMENT_CHECKBOX:
636     case XP_THEME_ELEMENT_RADIO_BUTTON:
637       switch (state)
638         {
639         case GTK_STATE_SELECTED:
640           ret = CBS_UNCHECKEDPRESSED;
641           break;
642
643         case GTK_STATE_PRELIGHT:
644           ret = CBS_UNCHECKEDHOT;
645           break;
646
647         case GTK_STATE_INSENSITIVE:
648           ret = CBS_UNCHECKEDDISABLED;
649           break;
650
651         default:
652           ret = CBS_UNCHECKEDNORMAL;
653         }
654       break;
655
656     case XP_THEME_ELEMENT_INCONSISTENT_CHECKBOX:
657       switch (state)
658         {
659         case GTK_STATE_SELECTED:
660           ret = CBS_MIXEDPRESSED;
661           break;
662
663         case GTK_STATE_PRELIGHT:
664           ret = CBS_MIXEDHOT;
665           break;
666
667         case GTK_STATE_INSENSITIVE:
668           ret = CBS_MIXEDDISABLED;
669           break;
670
671         default:
672           ret = CBS_MIXEDNORMAL;
673         }
674       break;
675
676     case XP_THEME_ELEMENT_PRESSED_CHECKBOX:
677     case XP_THEME_ELEMENT_PRESSED_RADIO_BUTTON:
678       switch (state)
679         {
680         case GTK_STATE_SELECTED:
681           ret = CBS_CHECKEDPRESSED;
682           break;
683
684         case GTK_STATE_PRELIGHT:
685           ret = CBS_CHECKEDHOT;
686           break;
687
688         case GTK_STATE_INSENSITIVE:
689           ret = CBS_CHECKEDDISABLED;
690           break;
691
692         default:
693           ret = CBS_CHECKEDNORMAL;
694         }
695       break;
696
697     case XP_THEME_ELEMENT_DEFAULT_BUTTON:
698       switch (state)
699         {
700         case GTK_STATE_ACTIVE:
701           ret = PBS_PRESSED;
702           break;
703
704         case GTK_STATE_PRELIGHT:
705           ret = PBS_HOT;
706           break;
707
708         case GTK_STATE_INSENSITIVE:
709           ret = PBS_DISABLED;
710           break;
711
712         default:
713           ret = PBS_DEFAULTED;
714         }
715       break;
716
717     case XP_THEME_ELEMENT_SPIN_BUTTON_DOWN:
718       switch (state)
719         {
720         case GTK_STATE_ACTIVE:
721           ret = DNS_PRESSED;
722           break;
723
724         case GTK_STATE_PRELIGHT:
725           ret = DNS_HOT;
726           break;
727
728         case GTK_STATE_INSENSITIVE:
729           ret = DNS_DISABLED;
730           break;
731
732         default:
733           ret = DNS_NORMAL;
734         }
735       break;
736
737     case XP_THEME_ELEMENT_SPIN_BUTTON_UP:
738       switch (state)
739         {
740         case GTK_STATE_ACTIVE:
741           ret = UPS_PRESSED;
742           break;
743
744         case GTK_STATE_PRELIGHT:
745           ret = UPS_HOT;
746           break;
747
748         case GTK_STATE_INSENSITIVE:
749           ret = UPS_DISABLED;
750           break;
751
752         default:
753           ret = UPS_NORMAL;
754         }
755       break;
756
757     case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_OPENED:
758       ret = GLPS_OPENED;
759       break;
760
761     case XP_THEME_ELEMENT_TREEVIEW_EXPANDER_CLOSED:
762       ret = GLPS_CLOSED;
763       break;
764
765     case XP_THEME_ELEMENT_PROGRESS_BAR_H:
766     case XP_THEME_ELEMENT_PROGRESS_BAR_V:
767     case XP_THEME_ELEMENT_PROGRESS_TROUGH_H:
768     case XP_THEME_ELEMENT_PROGRESS_TROUGH_V:
769       ret = 1;
770       break;
771
772     case XP_THEME_ELEMENT_MENU_ITEM:
773     case XP_THEME_ELEMENT_MENU_SEPARATOR:
774       switch (state)
775         {
776         case GTK_STATE_SELECTED:
777           ret = MS_SELECTED;
778           break;
779
780         case GTK_STATE_INSENSITIVE:
781           ret = MS_DEMOTED;
782           break;
783
784         default:
785           ret = MS_NORMAL;
786         }
787       break;
788
789     case XP_THEME_ELEMENT_LINE_H:
790       switch (state)
791         {
792           /* LHS_FLAT, LHS_RAISED, LHS_SUNKEN */
793           ret = LHS_RAISED;
794           break;
795         }
796       break;
797
798     case XP_THEME_ELEMENT_LINE_V:
799       switch (state)
800         {
801           /* LVS_FLAT, LVS_RAISED, LVS_SUNKEN */
802           ret = LVS_RAISED;
803           break;
804         }
805       break;
806
807     case XP_THEME_ELEMENT_SCALE_TROUGH_H:
808     case XP_THEME_ELEMENT_SCALE_TROUGH_V:
809       ret = TRS_NORMAL;
810       break;
811
812     default:
813       switch (state)
814         {
815         case GTK_STATE_ACTIVE:
816           ret = PBS_PRESSED;
817           break;
818
819         case GTK_STATE_PRELIGHT:
820           ret = PBS_HOT;
821           break;
822
823         case GTK_STATE_INSENSITIVE:
824           ret = PBS_DISABLED;
825           break;
826
827         default:
828           ret = PBS_NORMAL;
829         }
830     }
831
832   return ret;
833 }
834
835 gboolean
836 xp_theme_draw (GdkWindow *win, XpThemeElement element, GtkStyle *style,
837                int x, int y, int width, int height,
838                GtkStateType state_type, GdkRectangle *area)
839 {
840   HTHEME theme;
841   RECT rect, clip, *pClip;
842   int xoff, yoff;
843   HDC dc;
844   GdkDrawable *drawable;
845   int part_state;
846
847   if (!xp_theme_is_drawable (element))
848     return FALSE;
849
850   theme = xp_theme_get_handle_by_element (element);
851   if (!theme)
852     return FALSE;
853
854   /* FIXME: Recheck its function */
855   enable_theme_dialog_texture_func (GDK_WINDOW_HWND (win), ETDT_ENABLETAB);
856
857   if (!GDK_IS_WINDOW (win))
858     {
859       xoff = 0;
860       yoff = 0;
861       drawable = win;
862     }
863   else
864     {
865       gdk_window_get_internal_paint_info (win, &drawable, &xoff, &yoff);
866     }
867
868   rect.left = x - xoff;
869   rect.top = y - yoff;
870   rect.right = rect.left + width;
871   rect.bottom = rect.top + height;
872
873   if (area)
874     {
875       clip.left = area->x - xoff;
876       clip.top = area->y - yoff;
877       clip.right = clip.left + area->width;
878       clip.bottom = clip.top + area->height;
879
880       pClip = &clip;
881     }
882   else
883     {
884       pClip = NULL;
885     }
886
887   gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
888   dc = gdk_win32_hdc_get (drawable, style->dark_gc[state_type], 0);
889   if (!dc)
890     return FALSE;
891
892   part_state = xp_theme_map_gtk_state (element, state_type);
893
894   draw_theme_background_func (theme, dc, element_part_map[element],
895                               part_state, &rect, pClip);
896
897   gdk_win32_hdc_release (drawable, style->dark_gc[state_type], 0);
898
899   return TRUE;
900 }
901
902 gboolean
903 xp_theme_is_active (void)
904 {
905   return use_xp_theme;
906 }
907
908 gboolean
909 xp_theme_is_drawable (XpThemeElement element)
910 {
911   if (xp_theme_is_active ())
912     return (xp_theme_get_handle_by_element (element) != NULL);
913
914   return FALSE;
915 }
916
917 gboolean
918 xp_theme_get_system_font (XpThemeClass klazz, XpThemeFont fontId,
919                           OUT LOGFONT *lf)
920 {
921   if (xp_theme_is_active () && get_theme_sys_font_func != NULL)
922     {
923       HTHEME theme = xp_theme_get_handle_by_class (klazz);
924       int themeFont;
925
926       if (!theme)
927         return FALSE;
928
929       switch (fontId)
930         {
931         case XP_THEME_FONT_CAPTION:
932           themeFont = TMT_CAPTIONFONT;
933           break;
934
935         case XP_THEME_FONT_MENU:
936           themeFont = TMT_MENUFONT;
937           break;
938
939         case XP_THEME_FONT_STATUS:
940           themeFont = TMT_STATUSFONT;
941           break;
942
943         case XP_THEME_FONT_MESSAGE:
944         default:
945           themeFont = TMT_MSGBOXFONT;
946           break;
947         }
948
949       /* if theme is NULL, it will just return the GetSystemFont()
950          value */
951       return ((*get_theme_sys_font_func) (theme, themeFont, lf) == S_OK);
952     }
953
954   return FALSE;
955 }
956
957 gboolean
958 xp_theme_get_system_color (XpThemeClass klazz, int colorId,
959                            OUT DWORD *pColor)
960 {
961   if (xp_theme_is_active () && get_theme_sys_color_func != NULL)
962     {
963       HTHEME theme = xp_theme_get_handle_by_class (klazz);
964
965       /* if theme is NULL, it will just return the GetSystemColor()
966          value */
967       *pColor = (*get_theme_sys_color_func) (theme, colorId);
968       return TRUE;
969     }
970
971   return FALSE;
972 }
973
974 gboolean
975 xp_theme_get_system_metric (XpThemeClass klazz, int metricId, OUT int *pVal)
976 {
977   if (xp_theme_is_active () && get_theme_sys_metric_func != NULL)
978     {
979       HTHEME theme = xp_theme_get_handle_by_class (klazz);
980
981       /* if theme is NULL, it will just return the GetSystemMetrics()
982          value */
983       *pVal = (*get_theme_sys_metric_func) (theme, metricId);
984       return TRUE;
985     }
986
987   return FALSE;
988 }