source: trunk/src/user32/win32class.cpp@ 3153

Last change on this file since 3153 was 3153, checked in by cbratschi, 25 years ago

merged with Corel 20000317, small icon

File size: 18.3 KB
Line 
1/* $Id: win32class.cpp,v 1.16 2000-03-18 16:13:37 cbratschi Exp $ */
2/*
3 * Win32 Window Class Managment Code for OS/2
4 *
5 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
6 *
7 *
8 * TODO: Right now all class atoms are global. This must be changed.
9 * TODO: Global atoms of classes with CS_GLOBALCLASS flag are not deleted
10 * Must all be changed if we want to support global app classes
11 * that can be used by other apps. (low priority)
12 *
13 * Project Odin Software License can be found in LICENSE.TXT
14 *
15 */
16#include <os2win.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <stdarg.h>
21#include <assert.h>
22#include <misc.h>
23#include <win32class.h>
24#include <win32wnd.h>
25#include <win\winproc.h>
26
27#define DBG_LOCALLOG DBG_win32class
28#include "dbglocal.h"
29
30static fDestroyAll = FALSE;
31
32//******************************************************************************
33//Win32WndClass methods:
34//******************************************************************************
35Win32WndClass::Win32WndClass(WNDCLASSEXA *wndclass, BOOL fUnicode) : GenericObject(&wndclasses, OBJTYPE_CLASS)
36{
37 isUnicode = fUnicode;
38 processId = 0;
39
40 if(HIWORD(wndclass->lpszClassName)) {
41 if(isUnicode) {
42 INT len = lstrlenW((LPWSTR)wndclass->lpszClassName)+1;
43
44 classNameA = (PCHAR)_smalloc(len);
45 classNameW = (WCHAR *)_smalloc(len*sizeof(WCHAR));
46 }
47 else {
48 INT len = strlen(wndclass->lpszClassName)+1;
49
50 classNameA = (PCHAR)_smalloc(len);
51 classNameW = (WCHAR *)_smalloc(len*sizeof(WCHAR));
52 }
53 if(classNameA == NULL || classNameW == NULL) {
54 dprintf(("Win32Class ctr; classNameA/classNameW == NULL"));
55 exit(1);
56 }
57 if(isUnicode) {
58 lstrcpyW(classNameW, (LPWSTR)wndclass->lpszClassName);
59 UnicodeToAscii(classNameW, classNameA);
60 }
61 else {
62 strcpy((char *)classNameA, wndclass->lpszClassName);
63 AsciiToUnicode(classNameA, classNameW);
64 }
65 classAtom = 0;
66 //SvL: If a system control has already be registered, use that atom instead
67 // of creating a new one
68 if(wndclass->style & CS_GLOBALCLASS) {
69 classAtom = GlobalFindAtomA(classNameA);
70 }
71 if(!classAtom) classAtom = GlobalAddAtomA(classNameA);
72 }
73 else {
74 classNameA = NULL;
75 classNameW = NULL;
76 classAtom = (DWORD)wndclass->lpszClassName;
77 }
78 if(!(wndclass->style & CS_GLOBALCLASS)) {
79 processId = GetCurrentProcess();
80 }
81 menuNameA = 0;
82 menuNameW = 0;
83 setMenuName((LPSTR)wndclass->lpszMenuName);
84
85 dprintf(("USER32: Win32Class ctor\n"));
86 dprintf(("USER32: wndclass->style %X\n", wndclass->style));
87 dprintf(("USER32: wndclass->lpfnWndProc %X\n", wndclass->lpfnWndProc));
88 dprintf(("USER32: wndclass->cbClsExtra %X\n", wndclass->cbClsExtra));
89 dprintf(("USER32: wndclass->cbWndExtra %X\n", wndclass->cbWndExtra));
90 dprintf(("USER32: wndclass->hInstance %X\n", wndclass->hInstance));
91 dprintf(("USER32: wndclass->hIcon %X\n", wndclass->hIcon));
92 dprintf(("USER32: wndclass->hCursor %X\n", wndclass->hCursor));
93 dprintf(("USER32: wndclass->hbrBackground %X\n", wndclass->hbrBackground));
94 if(HIWORD(wndclass->lpszClassName))
95 dprintf(("USER32: wndclass->lpszClassName %s\n", classNameA));
96 else dprintf(("USER32: wndclass->lpszClassName %X\n", wndclass->lpszClassName));
97
98 if(HIWORD(wndclass->lpszMenuName)) {//convert string name identifier to numeric id
99 dprintf(("USER32: lpszMenuName %s\n", menuNameA));
100 }
101 else dprintf(("USER32: wndclass->lpszMenuName %X\n", menuNameA));
102 dprintf(("USER32: wndclass->hIconSm %X\n", wndclass->hIconSm));
103
104 nrExtraClassWords = wndclass->cbClsExtra;
105 nrExtraWindowWords = wndclass->cbWndExtra;
106 backgroundBrush = wndclass->hbrBackground;
107 hCursor = wndclass->hCursor;
108 hIcon = wndclass->hIcon;
109 hInstance = wndclass->hInstance;
110
111 if(wndclass->style & CS_CLASSDC) {
112 hdcClass = 0; //TODO:
113 }
114 else hdcClass = 0;
115
116 windowStyle = wndclass->style;
117
118 windowProc = 0;
119 WINPROC_SetProc((HWINDOWPROC *)&windowProc, wndclass->lpfnWndProc, (isUnicode) ? WIN_PROC_32W : WIN_PROC_32A, WIN_PROC_CLASS);
120 dprintf2(("Window class ptr %x", windowProc));
121
122 //User data class words/longs
123 if(nrExtraClassWords) {
124 userClassLong = (ULONG *)_smalloc(nrExtraClassWords);
125 if(userClassLong == NULL) {
126 dprintf(("Win32Class ctr: userClassLong == NULL!"));
127 exit(1);
128 }
129 memset(userClassLong, 0, nrExtraClassWords);
130 }
131 else userClassLong = NULL;
132
133 cWindows = 0;
134 hIconSm = wndclass->hIconSm;
135}
136//******************************************************************************
137//******************************************************************************
138Win32WndClass::~Win32WndClass()
139{
140 if(classNameA) {
141 dprintf(("Win32WndClass dtor, destroy class %s\n", classNameA));
142 }
143
144 //SvL: Don't delete global classes
145 if(classNameA && !(windowStyle & CS_GLOBALCLASS)) {
146 GlobalDeleteAtom(classAtom);
147 }
148
149 WINPROC_FreeProc(windowProc, WIN_PROC_CLASS);
150
151 if(userClassLong) free(userClassLong);
152 if(classNameA) free(classNameA);
153 if(classNameW) free(classNameW);
154 if(menuNameA && HIWORD(menuNameA)) {
155 free(menuNameA);
156 assert(menuNameW);
157 free(menuNameW);
158 }
159}
160//******************************************************************************
161//******************************************************************************
162void Win32WndClass::DestroyAll()
163{
164 fDestroyAll = TRUE;
165 GenericObject::DestroyAll(wndclasses);
166}
167//******************************************************************************
168//******************************************************************************
169BOOL Win32WndClass::hasClassName(LPSTR classname, BOOL fUnicode)
170{
171 if(HIWORD(classname) == 0) {
172 return classAtom == (DWORD)classname;
173 }
174 if(fUnicode) {
175 if(classNameW)
176 return (lstrcmpW(classNameW, (LPWSTR)classname) == 0);
177 return FALSE;
178 }
179 else {
180 if(classNameA)
181 return (strcmp(classNameA, classname) == 0);
182 return FALSE;
183 }
184}
185//******************************************************************************
186//******************************************************************************
187Win32WndClass *Win32WndClass::FindClass(HINSTANCE hInstance, LPSTR id)
188{
189 enterMutex(OBJTYPE_CLASS);
190
191 Win32WndClass *wndclass = (Win32WndClass *)wndclasses;
192
193 if(wndclass == NULL) {
194 leaveMutex(OBJTYPE_CLASS);
195 return(NULL);
196 }
197
198 if(HIWORD(id) != 0) {
199//CB: read comment below!
200 if(lstrcmpiA(wndclass->classNameA, id) == 0 && wndclass->hInstance == hInstance) {
201 leaveMutex(OBJTYPE_CLASS);
202 return(wndclass);
203 }
204 else {
205 wndclass = (Win32WndClass *)wndclass->GetNext();
206 while(wndclass != NULL) {
207 if(lstrcmpiA(wndclass->classNameA, id) == 0)
208 {
209 //SvL: According to Wine, if the instance handle is the one of the main exe, everything is ok
210 if(hInstance == NULL || GetModuleHandleA(NULL) == hInstance ||
211 wndclass->hInstance == hInstance)
212 {
213 leaveMutex(OBJTYPE_CLASS);
214 return(wndclass);
215 }
216 }
217 wndclass = (Win32WndClass *)wndclass->GetNext();
218 }
219 }
220 }
221 else {
222//CB: without HInstance check, test program finds class
223//CB: need more code to compare instance; convert 0 to exe module handle
224 if(wndclass->classAtom == (DWORD)id /*&& wndclass->hInstance == hInstance*/) {
225 leaveMutex(OBJTYPE_CLASS);
226 return(wndclass);
227 }
228 else {
229 wndclass = (Win32WndClass *)wndclass->GetNext();
230 while(wndclass != NULL) {
231 if(wndclass->classAtom == (DWORD)id /* && wndclass->hInstance == hInstance*/) {
232 leaveMutex(OBJTYPE_CLASS);
233 return(wndclass);
234 }
235 wndclass = (Win32WndClass *)wndclass->GetNext();
236 }
237 }
238 }
239 leaveMutex(OBJTYPE_CLASS);
240 dprintf(("Class %X (inst %X) not found!", id, hInstance));
241 return(NULL);
242}
243//******************************************************************************
244//An app can only access another process' class if it's global
245//(all system classes are global)
246//NOTE: NOT USED NOW
247//******************************************************************************
248BOOL Win32WndClass::isAppClass(ULONG curProcessId)
249{
250 if(windowStyle & CS_GLOBALCLASS)
251 return TRUE;
252
253 return curProcessId = processId;
254}
255//******************************************************************************
256//******************************************************************************
257BOOL Win32WndClass::getClassInfo(WNDCLASSEXA *wndclass)
258{
259 wndclass->cbClsExtra = nrExtraClassWords;
260 wndclass->cbWndExtra = nrExtraWindowWords;
261 wndclass->hbrBackground = backgroundBrush;
262 wndclass->hCursor = hCursor;
263 wndclass->hIcon = hIcon;
264 wndclass->hInstance = hInstance;
265 wndclass->lpszMenuName = (LPCTSTR)menuNameA;
266 wndclass->lpszClassName = (classNameA) ? (LPCTSTR)classNameA : (LPCTSTR)classAtom;
267 wndclass->style = windowStyle;
268 wndclass->lpfnWndProc = (WNDPROC)getClassLongA(GCL_WNDPROC, FALSE);
269 wndclass->hIconSm = hIconSm;
270 return(TRUE);
271}
272//******************************************************************************
273//******************************************************************************
274BOOL Win32WndClass::getClassInfo(WNDCLASSEXW *wndclass)
275{
276 wndclass->cbClsExtra = nrExtraClassWords;
277 wndclass->cbWndExtra = nrExtraWindowWords;
278 wndclass->hbrBackground = backgroundBrush;
279 wndclass->hCursor = hCursor;
280 wndclass->hIcon = hIcon;
281 wndclass->hInstance = hInstance;
282 wndclass->lpszMenuName = (LPCWSTR)menuNameW;
283 wndclass->lpszClassName = (classNameW) ? (LPCWSTR)classNameW : (LPCWSTR)classAtom;
284 wndclass->style = windowStyle;
285 wndclass->lpfnWndProc = (WNDPROC)getClassLongA(GCL_WNDPROC, TRUE);
286 wndclass->hIconSm = hIconSm;
287 return(TRUE);
288}
289//******************************************************************************
290//******************************************************************************
291ULONG Win32WndClass::getClassName(LPSTR lpszClassName, ULONG cchClassName)
292{
293 if(HIWORD(classNameA)) {
294 lstrcpynA(lpszClassName, classNameA, cchClassName-1);
295 return strlen(lpszClassName);
296 }
297 *(ULONG *)lpszClassName = classAtom;
298 return(sizeof(ULONG));
299}
300//******************************************************************************
301//******************************************************************************
302ULONG Win32WndClass::getClassName(LPWSTR lpszClassName, ULONG cchClassName)
303{
304 ULONG len;
305
306 if(HIWORD(classNameW)) {
307 lstrcpyW(lpszClassName, classNameW);
308 return lstrlenW(lpszClassName)*sizeof(WCHAR);
309 }
310 *(ULONG *)lpszClassName = classAtom;
311 return(sizeof(ULONG));
312}
313//******************************************************************************
314//******************************************************************************
315void Win32WndClass::setMenuName(LPSTR newMenuName)
316{
317 if(HIWORD(menuNameA)) {
318 free(menuNameA);
319 free(menuNameW);
320 menuNameA = 0;
321 menuNameW = 0;
322 }
323 if(HIWORD(newMenuName)) {
324 if(isUnicode) {
325 menuNameA = (PCHAR)_smalloc(lstrlenW((LPWSTR)newMenuName)+1);
326 menuNameW = (WCHAR *)_smalloc((lstrlenW((LPWSTR)newMenuName)+1)*sizeof(WCHAR));
327 }
328 else {
329 menuNameA = (PCHAR)_smalloc(strlen(newMenuName)+1);
330 menuNameW = (WCHAR *)_smalloc((strlen(newMenuName)+1)*sizeof(WCHAR));
331 }
332 if(menuNameA == NULL || menuNameW == NULL) {
333 dprintf(("Win32Class ctr; menuName/menuNameW == NULL"));
334 exit(1);
335 }
336 if(isUnicode) {
337 lstrcpyW(menuNameW, (LPWSTR)newMenuName);
338 UnicodeToAscii(menuNameW, menuNameA);
339 }
340 else {
341 strcpy((char *)menuNameA, newMenuName);
342 AsciiToUnicode(menuNameA, menuNameW);
343 }
344 }
345 else {//id
346 menuNameA = (PCHAR)newMenuName;
347 menuNameW = (WCHAR *)newMenuName;
348 }
349}
350//******************************************************************************
351//******************************************************************************
352ULONG Win32WndClass::getClassLongA(int index, BOOL fUnicode)
353{
354 switch(index) {
355 case GCL_CBCLSEXTRA:
356 return nrExtraClassWords;
357 case GCL_CBWNDEXTRA:
358 return nrExtraWindowWords;
359 case GCL_HBRBACKGROUND:
360 return backgroundBrush;
361 case GCL_HCURSOR:
362 return hCursor;
363 case GCL_HICON:
364 return hIcon;
365 case GCL_HICONSM:
366 return hIconSm;
367 case GCL_HMODULE:
368 return hInstance;
369 case GCL_MENUNAME:
370 return (isUnicode) ? (ULONG)menuNameW : (ULONG)menuNameA;
371 case GCL_STYLE:
372 return windowStyle;
373 case GCL_WNDPROC:
374 return (ULONG) WINPROC_GetProc(windowProc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
375 case GCW_ATOM: //TODO: does this really happen in windows?
376 SetLastError(ERROR_INVALID_PARAMETER);
377 return 0;
378 default:
379 if(index > 0 && index < nrExtraClassWords - sizeof(ULONG)) {
380 return userClassLong[index];
381 }
382 SetLastError(ERROR_INVALID_PARAMETER);
383 return 0;
384 }
385}
386//******************************************************************************
387//******************************************************************************
388WORD Win32WndClass::getClassWord(int index)
389{
390 switch(index) {
391 case GCW_ATOM:
392 return (WORD)classAtom;
393 default:
394 if(index > 0 && index < nrExtraClassWords - sizeof(WORD)) {
395 return ((WORD *)userClassLong)[index];
396 }
397 SetLastError(ERROR_INVALID_PARAMETER);
398 return 0;
399 }
400}
401//******************************************************************************
402//TODO: What effects what immediately?
403//******************************************************************************
404ULONG Win32WndClass::setClassLongA(int index, LONG lNewVal, BOOL fUnicode)
405{
406 ULONG rc;
407
408 if(classNameA) {
409 dprintf2(("Win32WndClass::setClassLongA %s: %d %x", classNameA, index, lNewVal));
410 }
411 else dprintf2(("Win32WndClass::setClassLongA %d: %d %x", classAtom, index, lNewVal));
412 switch(index) {
413 case GCL_CBCLSEXTRA: //TODO (doesn't affect allocated classes, so what does it do?)
414 rc = nrExtraClassWords;
415// nrExtraClassWords = lNewVal;
416 break;
417 case GCL_CBWNDEXTRA:
418 rc = nrExtraWindowWords;
419 nrExtraWindowWords = lNewVal;
420 break;
421 case GCL_HBRBACKGROUND:
422 rc = backgroundBrush;
423 backgroundBrush = lNewVal;
424 break;
425 case GCL_HCURSOR:
426 rc = hCursor;
427 hCursor = lNewVal;
428 break;
429 case GCL_HICON:
430 rc = hIcon;
431 hIcon = lNewVal;
432 break;
433 case GCL_HICONSM:
434 rc = hIconSm;
435 hIconSm = lNewVal;
436 break;
437 case GCL_HMODULE:
438 rc = hInstance;
439 hInstance = lNewVal;
440 break;
441 case GCL_MENUNAME:
442 rc = 0; //old value is meaningless (according to Wine)
443 setMenuName((LPSTR)lNewVal);
444 break;
445 case GCL_STYLE:
446 rc = windowStyle;
447 windowStyle = lNewVal;
448 break;
449 case GCL_WNDPROC:
450 rc = (LONG)WINPROC_GetProc(windowProc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A );
451 WINPROC_SetProc((HWINDOWPROC *)&windowProc, (WNDPROC)lNewVal, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A, WIN_PROC_CLASS );
452 break;
453 case GCW_ATOM: //TODO: does this really happen in windows?
454 SetLastError(ERROR_INVALID_PARAMETER);
455 return 0;
456 default:
457 if(index > 0 && index < nrExtraClassWords - sizeof(ULONG)) {
458 rc = userClassLong[index];
459 userClassLong[index] = lNewVal;
460 return(rc);
461 }
462 SetLastError(ERROR_INVALID_PARAMETER);
463 return 0;
464 }
465 return(rc);
466}
467//******************************************************************************
468//******************************************************************************
469WORD Win32WndClass::setClassWord(int index, WORD wNewVal)
470{
471 WORD rc;
472
473 switch(index) {
474 case GCW_ATOM:
475 rc = (WORD)classAtom;
476 classAtom = wNewVal;
477 return(rc);
478 default:
479 if(index > 0 && index < nrExtraClassWords - sizeof(WORD)) {
480 rc = ((WORD *)userClassLong)[index];
481 ((WORD *)userClassLong)[index] = wNewVal;
482 return(rc);
483 }
484 SetLastError(ERROR_INVALID_PARAMETER);
485 return 0;
486 }
487}
488//******************************************************************************
489//FIXME: Windows that still exists with this class
490//******************************************************************************
491void Win32WndClass::UnregisterClassA(HINSTANCE hinst, LPSTR id)
492{
493 Win32WndClass *wndclass;
494
495 wndclass = FindClass(hinst, id);
496 if(wndclass) {
497 delete wndclass;
498 return;
499 }
500 dprintf(("::UnregisterClass, couldn't find class %X!!\n", id));
501}
502//******************************************************************************
503//******************************************************************************
504GenericObject *Win32WndClass::wndclasses = NULL;
Note: See TracBrowser for help on using the repository browser.