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