Release 941210
[wine] / windows / class.c
1 /*
2  * Window classes functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
6 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
7 */
8
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include "class.h"
13 #include "user.h"
14 #include "win.h"
15 #include "dce.h"
16 #include "stddebug.h"
17 /* #define DEBUG_CLASS */
18 #include "debug.h"
19
20
21 static HCLASS firstClass = 0;
22
23
24 /***********************************************************************
25  *           CLASS_FindClassByName
26  *
27  * Return a handle and a pointer to the class.
28  * 'ptr' can be NULL if the pointer is not needed.
29  */
30 HCLASS CLASS_FindClassByName( char * name, WORD hinstance, CLASS **ptr )
31 {
32     ATOM atom;
33     HCLASS class;
34     CLASS * classPtr;
35
36       /* First search task-specific classes */
37
38     if ((atom = /*FindAtom*/GlobalFindAtom( name )) != 0)
39     {
40         for (class = firstClass; (class); class = classPtr->hNext)
41         {
42             classPtr = (CLASS *) USER_HEAP_ADDR(class);
43             if (classPtr->wc.style & CS_GLOBALCLASS) continue;
44             if ((classPtr->atomName == atom) && 
45                 (( hinstance==0xffff )|| (hinstance == classPtr->wc.hInstance)))
46             {
47                 if (ptr) *ptr = classPtr;
48                 return class;
49             }
50         }
51     }
52     
53       /* Then search global classes */
54
55     if ((atom = GlobalFindAtom( name )) != 0)
56     {
57         for (class = firstClass; (class); class = classPtr->hNext)
58         {
59             classPtr = (CLASS *) USER_HEAP_ADDR(class);
60             if (!(classPtr->wc.style & CS_GLOBALCLASS)) continue;
61             if (classPtr->atomName == atom)
62             {
63                 if (ptr) *ptr = classPtr;
64                 return class;
65             }
66         }
67     }
68
69     return 0;
70 }
71
72
73 /***********************************************************************
74  *           CLASS_FindClassPtr
75  *
76  * Return a pointer to the CLASS structure corresponding to a HCLASS.
77  */
78 CLASS * CLASS_FindClassPtr( HCLASS hclass )
79 {
80     CLASS * ptr;
81     
82     if (!hclass) return NULL;
83     ptr = (CLASS *) USER_HEAP_ADDR( hclass );
84     if (ptr->wMagic != CLASS_MAGIC) return NULL;
85     return ptr;
86 }
87
88
89 /***********************************************************************
90  *           RegisterClass    (USER.57)
91  */
92 ATOM RegisterClass( LPWNDCLASS class )
93 {
94     CLASS * newClass, * prevClassPtr;
95     HCLASS handle, prevClass;
96     int classExtra;
97
98     dprintf_class(stddeb, "RegisterClass: wndproc=%p hinst=%d name='%s' background %x\n", 
99             class->lpfnWndProc, class->hInstance, class->lpszClassName,
100             class->hbrBackground );
101
102       /* Check if a class with this name already exists */
103
104     prevClass = CLASS_FindClassByName( class->lpszClassName, class->hInstance,
105         &prevClassPtr );
106     if (prevClass)
107     {
108           /* Class can be created only if it is local and */
109           /* if the class with the same name is global.   */
110
111         if (class->style & CS_GLOBALCLASS) return 0;
112         if (!(prevClassPtr->wc.style & CS_GLOBALCLASS)) return 0;
113     }
114
115       /* Create class */
116
117     classExtra = (class->cbClsExtra < 0) ? 0 : class->cbClsExtra;
118     handle = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(CLASS) + classExtra );
119     if (!handle) return 0;
120     newClass = (CLASS *) USER_HEAP_ADDR( handle );
121     newClass->hNext         = firstClass;
122     newClass->wMagic        = CLASS_MAGIC;
123     newClass->cWindows      = 0;  
124     newClass->wc            = *class;
125     newClass->wc.cbWndExtra = (class->cbWndExtra < 0) ? 0 : class->cbWndExtra;
126     newClass->wc.cbClsExtra = classExtra;
127
128     /*if (newClass->wc.style & CS_GLOBALCLASS)*/
129         newClass->atomName = GlobalAddAtom( class->lpszClassName );
130     /*else newClass->atomName = AddAtom( class->lpszClassName );*/
131     newClass->wc.lpszClassName = NULL; 
132
133     if (newClass->wc.style & CS_CLASSDC)
134         newClass->hdce = DCE_AllocDCE( DCE_CLASS_DC );
135     else newClass->hdce = 0;
136
137       /* Make a copy of the menu name (only if it is a string) */
138
139     if ((int)class->lpszMenuName & 0xffff0000)
140     {
141         HANDLE hname;
142         hname = USER_HEAP_ALLOC( GMEM_MOVEABLE, strlen(class->lpszMenuName)+1);
143         if (hname)
144         {
145             newClass->wc.lpszMenuName = (char *)USER_HEAP_ADDR( hname );
146             strcpy( newClass->wc.lpszMenuName, class->lpszMenuName );
147         }
148     }
149
150     if (classExtra) memset( newClass->wExtra, 0, classExtra );
151     firstClass = handle;
152     return newClass->atomName;
153 }
154
155
156 /***********************************************************************
157  *           UnregisterClass    (USER.403)
158  */
159 BOOL UnregisterClass( LPSTR className, HANDLE instance )
160 {
161     HANDLE class, prevClass;
162     CLASS * classPtr, * prevClassPtr;
163     
164       /* Check if we can remove this class */
165     class = CLASS_FindClassByName( className, instance, &classPtr );
166     if (!class) return FALSE;
167     if ((classPtr->wc.hInstance != instance) || (classPtr->cWindows > 0))
168         return FALSE;
169     
170       /* Remove the class from the linked list */
171     if (firstClass == class) firstClass = classPtr->hNext;
172     else
173     {
174         for (prevClass = firstClass; prevClass; prevClass=prevClassPtr->hNext)
175         {
176             prevClassPtr = (CLASS *) USER_HEAP_ADDR(prevClass);
177             if (prevClassPtr->hNext == class) break;
178         }
179         if (!prevClass)
180         {
181             fprintf(stderr, "ERROR: Class list corrupted\n" );
182             return FALSE;
183         }
184         prevClassPtr->hNext = classPtr->hNext;
185     }
186
187       /* Delete the class */
188     if (classPtr->hdce) DCE_FreeDCE( classPtr->hdce );
189     if (classPtr->wc.hbrBackground) DeleteObject( classPtr->wc.hbrBackground );
190     /*if (classPtr->wc.style & CS_GLOBALCLASS)*/ GlobalDeleteAtom( classPtr->atomName );
191     /*else DeleteAtom( classPtr->atomName );*/
192     if ((int)classPtr->wc.lpszMenuName & 0xffff0000)
193         USER_HEAP_FREE( (int)classPtr->wc.lpszMenuName & 0xffff );
194     USER_HEAP_FREE( class );
195     return TRUE;
196 }
197
198
199 /***********************************************************************
200  *           GetClassWord    (USER.129)
201  */
202 WORD GetClassWord( HWND hwnd, short offset )
203 {
204     return (WORD)GetClassLong( hwnd, offset );
205 }
206
207
208 /***********************************************************************
209  *           SetClassWord    (USER.130)
210  */
211 WORD SetClassWord( HWND hwnd, short offset, WORD newval )
212 {
213     CLASS * classPtr;
214     WND * wndPtr;
215     WORD *ptr, retval = 0;
216     
217     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
218     if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 0;
219     ptr = (WORD *)(((char *)classPtr->wExtra) + offset);
220     retval = *ptr;
221     *ptr = newval;
222     return retval;
223 }
224
225
226 /***********************************************************************
227  *           GetClassLong    (USER.131)
228  */
229 LONG GetClassLong( HWND hwnd, short offset )
230 {
231     CLASS * classPtr;
232     WND * wndPtr;
233     
234     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
235     if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 0;
236     return *(LONG *)(((char *)classPtr->wExtra) + offset);
237 }
238
239
240 /***********************************************************************
241  *           SetClassLong    (USER.132)
242  */
243 LONG SetClassLong( HWND hwnd, short offset, LONG newval )
244 {
245     CLASS * classPtr;
246     WND * wndPtr;
247     LONG *ptr, retval = 0;
248     
249     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
250     if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 0;
251     ptr = (LONG *)(((char *)classPtr->wExtra) + offset);
252     retval = *ptr;
253     *ptr = newval;
254     return retval;
255 }
256
257
258 /***********************************************************************
259  *           GetClassName      (USER.58)
260  */
261 int GetClassName(HWND hwnd, LPSTR lpClassName, short maxCount)
262 {
263     WND *wndPtr;
264     CLASS *classPtr;
265
266     /* FIXME: We have the find the correct hInstance */
267     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
268     if (!(classPtr = CLASS_FindClassPtr(wndPtr->hClass))) return 0;
269
270     return (GetAtomName(classPtr->atomName, lpClassName, maxCount));
271 }
272
273
274 /***********************************************************************
275  *           GetClassInfo      (USER.404)
276  */
277 BOOL GetClassInfo(HANDLE hInstance, LPSTR lpClassName, 
278                                     LPWNDCLASS lpWndClass)
279 {
280     CLASS *classPtr;
281
282     if (HIWORD(lpClassName))
283     {
284         dprintf_class(stddeb, "GetClassInfo   hInstance=%04x  lpClassName=%s\n",
285             hInstance, lpClassName);
286     }
287     else
288        dprintf_class(stddeb, "GetClassInfo   hInstance=%04x  lpClassName=#%d\n",
289             hInstance, (int)lpClassName);    
290
291
292     /* if (!(CLASS_FindClassByName(lpClassName, &classPtr))) return FALSE; */
293     if (!(CLASS_FindClassByName(lpClassName, hInstance, &classPtr)))
294     {
295         if (!HIWORD(lpClassName))
296         {
297             char temp[10];
298             sprintf(temp, "#%d", (int)lpClassName);
299             if (!(CLASS_FindClassByName(temp, hInstance, &classPtr))) return FALSE;        
300     
301         }
302         else return FALSE;
303     }
304
305     if (hInstance && (hInstance != classPtr->wc.hInstance)) return FALSE;
306
307     memcpy(lpWndClass, &(classPtr->wc), sizeof(WNDCLASS));
308     return TRUE;
309 }