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