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