Use "static const" rather than "const static" as gcc -W complains
[wine] / dlls / comctl32 / theming.c
1 /*
2  * Theming - Initialization
3  *
4  * Copyright (c) 2005 by Frank Richter
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "comctl32.h"
29 #include "wine/debug.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(theming);
32
33 typedef LRESULT (CALLBACK* THEMING_SUBCLASSPROC)(HWND, UINT, WPARAM, LPARAM,
34     ULONG_PTR);
35
36 extern LRESULT CALLBACK THEMING_ComboSubclassProc (HWND, UINT, WPARAM, LPARAM,
37                                                    ULONG_PTR);
38 extern LRESULT CALLBACK THEMING_DialogSubclassProc (HWND, UINT, WPARAM, LPARAM,
39                                                     ULONG_PTR);
40 extern LRESULT CALLBACK THEMING_EditSubclassProc (HWND, UINT, WPARAM, LPARAM,
41                                                   ULONG_PTR);
42 extern LRESULT CALLBACK THEMING_ListBoxSubclassProc (HWND, UINT, WPARAM, LPARAM,
43                                                      ULONG_PTR);
44
45 static const WCHAR dialogClass[] = {'#','3','2','7','7','0',0};
46 static const WCHAR comboLboxClass[] = {'C','o','m','b','o','L','b','o','x',0};
47
48 static const struct ThemingSubclass
49 {
50     const WCHAR* className;
51     THEMING_SUBCLASSPROC subclassProc;
52 } subclasses[] = {
53     /* Note: list must be sorted by class name */
54     {dialogClass,          THEMING_DialogSubclassProc},
55     {WC_COMBOBOXW,         THEMING_ComboSubclassProc},
56     {comboLboxClass,       THEMING_ListBoxSubclassProc},
57     {WC_EDITW,             THEMING_EditSubclassProc},
58     {WC_LISTBOXW,          THEMING_ListBoxSubclassProc}
59 };
60
61 #define NUM_SUBCLASSES        (sizeof(subclasses)/sizeof(subclasses[0]))
62
63 static WNDPROC originalProcs[NUM_SUBCLASSES];
64 static ATOM atRefDataProp;
65 static ATOM atSubclassProp;
66
67 /* Generate a number of subclass window procs.
68  * With a single proc alone, we can't really reliably find out the superclass,
69  * so have one for each subclass. The subclass number is also stored in a prop
70  * since it's needed by THEMING_CallOriginalClass(). Then, the the subclass 
71  * proc and ref data are fetched and the proc called.
72  */
73 #define MAKE_SUBCLASS_PROC(N)                                               \
74 static LRESULT CALLBACK subclass_proc ## N (HWND wnd, UINT msg,             \
75                                             WPARAM wParam, LPARAM lParam)   \
76 {                                                                           \
77     LRESULT result;                                                         \
78     ULONG_PTR refData;                                                      \
79     SetPropW (wnd, MAKEINTATOMW (atSubclassProp), (HANDLE)N);               \
80     refData = (ULONG_PTR)GetPropW (wnd, MAKEINTATOMW (atRefDataProp));      \
81     TRACE ("%d; (%p, %x, %x, %lx, %lx)\n", N, wnd, msg, wParam, lParam,     \
82         refData);                                                           \
83     result = subclasses[N].subclassProc (wnd, msg, wParam, lParam, refData);\
84     TRACE ("result = %lx\n", result);                                       \
85     return result;                                                          \
86 }
87
88 MAKE_SUBCLASS_PROC(0)
89 MAKE_SUBCLASS_PROC(1)
90 MAKE_SUBCLASS_PROC(2)
91 MAKE_SUBCLASS_PROC(3)
92 MAKE_SUBCLASS_PROC(4)
93
94 static const WNDPROC subclassProcs[NUM_SUBCLASSES] = {
95     subclass_proc0,
96     subclass_proc1,
97     subclass_proc2,
98     subclass_proc3,
99     subclass_proc4
100 };
101
102 /***********************************************************************
103  * THEMING_Initialize
104  *
105  * Register classes for standard controls that will shadow the system
106  * classes.
107  */
108 void THEMING_Initialize (void)
109 {
110     int i;
111     static const WCHAR subclassPropName[] = 
112         { 'C','C','3','2','T','h','e','m','i','n','g','S','u','b','C','l',0 };
113     static const WCHAR refDataPropName[] = 
114         { 'C','C','3','2','T','h','e','m','i','n','g','D','a','t','a',0 };
115
116     atSubclassProp = GlobalAddAtomW (subclassPropName);
117     atRefDataProp = GlobalAddAtomW (refDataPropName);
118
119     for (i = 0; i < NUM_SUBCLASSES; i++)
120     {
121         WNDCLASSEXW class;
122
123         class.cbSize = sizeof(class);
124         class.style |= CS_GLOBALCLASS;
125         GetClassInfoExW (NULL, subclasses[i].className, &class);
126         originalProcs[i] = class.lpfnWndProc;
127         class.lpfnWndProc = subclassProcs[i];
128         
129         if (!class.lpfnWndProc)
130         {
131             ERR("Missing proc for class %s\n", 
132                 debugstr_w (subclasses[i].className));
133             continue;
134         }
135
136         if (!RegisterClassExW (&class))
137         {
138             ERR("Could not re-register class %s: %lx\n", 
139                 debugstr_w (subclasses[i].className), GetLastError ());
140         }
141         else
142         {
143             TRACE("Re-registered class %s\n", 
144                 debugstr_w (subclasses[i].className));
145         }
146     }
147 }
148
149 /***********************************************************************
150  * THEMING_Uninitialize
151  *
152  * Unregister shadow classes for standard controls.
153  */
154 void THEMING_Uninitialize (void)
155 {
156     int i;
157     for (i = 0; i < NUM_SUBCLASSES; i++)
158     {
159         UnregisterClassW (subclasses[i].className, NULL);
160     }
161 }
162
163 /***********************************************************************
164  * THEMING_CallOriginalClass
165  *
166  * Determines the original window proc and calls it.
167  */
168 LRESULT THEMING_CallOriginalClass (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
169 {
170     INT_PTR subclass = (INT_PTR)GetPropW (wnd, MAKEINTATOMW (atSubclassProp));
171     WNDPROC oldProc = originalProcs[subclass];
172     return CallWindowProcW (oldProc, wnd, msg, wParam, lParam);
173 }
174
175 /***********************************************************************
176  * THEMING_SetSubclassData
177  *
178  * Update the "refData" value of the subclassed window.
179  */
180 void THEMING_SetSubclassData (HWND wnd, ULONG_PTR refData)
181 {
182     SetPropW (wnd, MAKEINTATOMW (atRefDataProp), (HANDLE)refData);
183 }