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