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