00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include <os2win.h>
00046 #include <stdio.h>
00047 #include <string.h>
00048 #include <winicon.h>
00049 #include <win\cursoricon.h>
00050 #include <objhandle.h>
00051 #include "dib.h"
00052 #include <heapstring.h>
00053 #include <win\virtual.h>
00054 #include "initterm.h"
00055 #include "oslibres.h"
00056 #include "oslibwin.h"
00057 #include "dc.h"
00058
00059 #define DBG_LOCALLOG DBG_winicon
00060 #include "dbglocal.h"
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 typedef struct tagICONCACHE
00071 {
00072 struct tagICONCACHE *next;
00073
00074 HMODULE hModule;
00075 HRSRC hRsrc;
00076 HRSRC hGroupRsrc;
00077 HANDLE handle;
00078 INT count;
00079 } ICONCACHE;
00080
00081 static ICONCACHE *IconAnchor = NULL;
00082 static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT;
00083 static WORD ICON_HOTSPOT = 0x4242;
00084 static HCURSOR hActiveCursor = 0;
00085 static HCURSOR hActiveCursorPM = 0;
00086
00087
00088 static HGLOBAL CURSORICON_CreateFromResource( HINSTANCE hInstance, DWORD dwResGroupId, HGLOBAL hObj, LPBYTE bits,
00089 UINT cbSize, BOOL bIcon, DWORD dwVersion, INT width, INT height, UINT loadflags );
00090 static HGLOBAL CURSORICON_Copy( HGLOBAL handle );
00091 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
00092 int height, int colors );
00093 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
00094 int width, int height, int color);
00095 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
00096 CURSORICONDIR **res, LPBYTE **ptr);
00097
00098 static INT CURSORICON_DelSharedIcon( HANDLE handle );
00099 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle );
00100 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc );
00101 static ICONCACHE* CURSORICON_FindCache(HANDLE handle);
00102
00103 static HGLOBAL CreateCursorIconIndirect( HINSTANCE hInstance,
00104 CURSORICONINFO *info,
00105 LPCVOID lpANDbits,
00106 LPCVOID lpXORbits, BOOL fIcon);
00107
00108
00109
00110
00111 HICON WIN32API CreateIcon(HINSTANCE hInstance, INT nWidth,
00112 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
00113 LPCVOID lpANDbits, LPCVOID lpXORbits )
00114 {
00115 CURSORICONINFO info;
00116
00117 dprintf(("USER32: CreateIcon (%d,%d), %d, %x, %x", nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits));
00118
00119 info.ptHotSpot.x = ICON_HOTSPOT;
00120 info.ptHotSpot.y = ICON_HOTSPOT;
00121 info.nWidth = nWidth;
00122 info.nHeight = nHeight;
00123 info.nWidthBytes = 0;
00124 info.bPlanes = bPlanes;
00125 info.bBitsPerPixel = bBitsPixel;
00126 info.hInstance = hInstance;
00127 info.dwResGroupId = -1;
00128 info.hColorBmp = 0;
00129 return CreateCursorIconIndirect(0, &info, lpANDbits, lpXORbits, TRUE);
00130 }
00131
00132
00133
00134 HICON WIN32API CreateIconFromResource(LPBYTE bits, UINT cbSize,
00135 BOOL bIcon, DWORD dwVersion)
00136 {
00137 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
00138 }
00139
00140
00141 HICON WIN32API CreateIconFromResourceEx(LPBYTE bits, UINT cbSize,
00142 BOOL bIcon, DWORD dwVersion,
00143 INT width, INT height,
00144 UINT cFlag )
00145 {
00146 dprintf(("USER32: CreateIconFromResourceEx %X %d %d %X %d %d %X,", bits, cbSize, bIcon, dwVersion, width, height, cFlag));
00147 return CURSORICON_CreateFromResource(0, -1, 0, bits, cbSize, bIcon, dwVersion, width, height, cFlag );
00148 }
00149
00150
00151
00152 HICON WINAPI CreateIconIndirect(ICONINFO *iconinfo)
00153 {
00154 BITMAP bmpXor,bmpAnd;
00155 HICON hObj;
00156 int sizeXor,sizeAnd,colortablesize;
00157
00158 dprintf(("USER32: CreateIconIndirect %x %x %x %s", iconinfo, iconinfo->hbmMask, iconinfo->hbmColor, (iconinfo->fIcon) ? "icon" : "cursor"));
00159
00160 GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
00161 GetObjectA( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
00162
00163 colortablesize = 0;
00164
00165 if(bmpXor.bmBitsPixel <= 8) {
00166 colortablesize = sizeof(RGBQUAD)*(1<<bmpXor.bmBitsPixel);
00167 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes + colortablesize;
00168 }
00169 else sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
00170
00171 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
00172
00173 hObj = GlobalAlloc( GMEM_MOVEABLE, sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
00174 if (hObj)
00175 {
00176 CURSORICONINFO *info;
00177
00178 info = (CURSORICONINFO *)GlobalLock( hObj );
00179
00180
00181 if (iconinfo->fIcon)
00182 {
00183 info->ptHotSpot.x = ICON_HOTSPOT;
00184 info->ptHotSpot.y = ICON_HOTSPOT;
00185 }
00186 else
00187 {
00188 info->ptHotSpot.x = iconinfo->xHotspot;
00189 info->ptHotSpot.y = iconinfo->yHotspot;
00190 }
00191
00192 info->nWidth = bmpXor.bmWidth;
00193 info->nHeight = bmpXor.bmHeight;
00194 info->nWidthBytes = bmpXor.bmWidthBytes;
00195 info->bPlanes = bmpXor.bmPlanes;
00196 info->bBitsPerPixel = bmpXor.bmBitsPixel;
00197 info->hInstance = -1;
00198 info->dwResGroupId = -1;
00199 info->hColorBmp = 0;
00200
00201
00202 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
00203 if(bmpXor.bmBitsPixel > 1)
00204 {
00205 BITMAPINFO* pInfo = (BITMAPINFO *)malloc(sizeof(BITMAPINFO)+colortablesize+3*sizeof(DWORD));
00206 HBITMAP oldbmp;
00207 HDC hdc;
00208
00209 hdc = CreateCompatibleDC(0);
00210
00211 memset(pInfo, 0, sizeof(BITMAPINFO)+colortablesize+3*sizeof(DWORD));
00212 pInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
00213 pInfo->bmiHeader.biPlanes = info->bPlanes;
00214 pInfo->bmiHeader.biBitCount = info->bBitsPerPixel;
00215
00216 GetDIBits(hdc, iconinfo->hbmColor, 0, bmpXor.bmHeight, (char *)(info + 1) + sizeAnd + colortablesize, pInfo, DIB_RGB_COLORS);
00217 if(colortablesize) {
00218 memcpy((char *)(info + 1) + sizeAnd, (char *)&pInfo->bmiHeader + pInfo->bmiHeader.biSize, colortablesize);
00219 }
00220
00221 DeleteDC(hdc);
00222 free(pInfo);
00223 }
00224 else {
00225 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
00226 }
00227
00228 #ifdef __WIN32OS2__
00229 info->hColorBmp = OSLibWinCreatePointer(info, (char*)(info + 1), (LPBITMAP_W)&bmpAnd, (char*)(info + 1) + sizeAnd, (LPBITMAP_W)&bmpXor, iconinfo->fIcon == FALSE);
00230 #endif
00231 GlobalUnlock(hObj);
00232
00233 #ifdef __WIN32OS2__
00234 HICON hIcon;
00235 if(ObjAllocateHandle(&hIcon, (DWORD)hObj, USEROBJ_CURSORICON) == FALSE) {
00236 GlobalFree(hObj);
00237 dprintf(("ERROR: CreateIconIndirect ObjAllocateHandle failed!!"));
00238 return 0;
00239 }
00240 #endif
00241 dprintf(("USER32: CreateIconIndirect %x returned %x", iconinfo, hIcon));
00242 return hIcon;
00243 }
00244 else {
00245 dprintf(("ERROR: CreateIconIndirect GlobalAlloc failed!!"));
00246 return 0;
00247 }
00248 }
00249
00250
00251 BOOL WIN32API DestroyIcon( HICON hIcon)
00252 {
00253 dprintf(("USER32: DestroyIcon %x", hIcon));
00254 return CURSORICON_Destroy( hIcon, 0 );
00255 }
00256
00257
00258 HICON WIN32API CopyIcon( HICON hIcon)
00259 {
00260 dprintf(("USER32: CopyIcon %x", hIcon));
00261 return CURSORICON_Copy( hIcon );
00262 }
00263
00264
00265 HICON WIN32API GetOS2Icon(HICON hIcon)
00266 {
00267 CURSORICONINFO *ciconinfo;
00268
00269 hIcon = ObjGetHandleData(hIcon, USEROBJ_CURSORICON);
00270 if(hIcon == -1) {
00271 dprintf(("ERROR: Invalid cursor/icon!"));
00272 return 0;
00273 }
00274 ciconinfo = (CURSORICONINFO *)GlobalLock((HGLOBAL)hIcon);
00275 if (!ciconinfo)
00276 return 0;
00277 HICON hOS2Icon = ciconinfo->hColorBmp;
00278 GlobalUnlock(hIcon);
00279 return hOS2Icon;
00280 }
00281
00282
00283
00284 BOOL WINAPI GetIconInfo(HICON hIcon, ICONINFO *iconinfo)
00285 {
00286 CURSORICONINFO *ciconinfo;
00287
00288 dprintf(("GetIconInfo %x %x", hIcon, iconinfo));
00289
00290 #ifdef __WIN32OS2__
00291 hIcon = ObjGetHandleData(hIcon, USEROBJ_CURSORICON);
00292 if(hIcon == -1) {
00293 dprintf(("ERROR: Invalid cursor/icon!"));
00294 return 0;
00295 }
00296 #endif
00297 ciconinfo = (CURSORICONINFO *)GlobalLock((HGLOBAL)hIcon);
00298 if (!ciconinfo)
00299 return FALSE;
00300
00301 if((ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
00302 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT))
00303 {
00304 iconinfo->fIcon = TRUE;
00305 iconinfo->xHotspot = ciconinfo->nWidth / 2;
00306 iconinfo->yHotspot = ciconinfo->nHeight / 2;
00307 }
00308 else
00309 {
00310 iconinfo->fIcon = FALSE;
00311 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
00312 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
00313 }
00314
00315
00316
00317 if(ciconinfo->bBitsPerPixel > 1)
00318 {
00319 BITMAPINFO* pInfo;
00320 int colorsize = 0;
00321 int coloroff;
00322
00323 HDC hdc = CreateCompatibleDC(0);
00324
00325 if(ciconinfo->bBitsPerPixel <= 8) {
00326 colorsize = (1<<ciconinfo->bBitsPerPixel)*sizeof(RGBQUAD);
00327 }
00328 else {
00329 colorsize = 3*sizeof(DWORD);
00330 }
00331 pInfo = (BITMAPINFO *)malloc(ciconinfo->nHeight * ciconinfo->nWidthBytes + colorsize + sizeof(BITMAPINFO));
00332 memset(pInfo, 0, sizeof(BITMAPINFO)+colorsize);
00333
00334 pInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
00335 pInfo->bmiHeader.biWidth = ciconinfo->nWidth;
00336 pInfo->bmiHeader.biHeight = ciconinfo->nHeight,
00337 pInfo->bmiHeader.biPlanes = ciconinfo->bPlanes;
00338 pInfo->bmiHeader.biBitCount = ciconinfo->bBitsPerPixel;
00339 pInfo->bmiHeader.biSizeImage= ciconinfo->nHeight * ciconinfo->nWidthBytes;
00340
00341
00342 coloroff = ciconinfo->nHeight * BITMAP_GetWidthBytes (ciconinfo->nWidth, 1);
00343
00344 char *src = (char *)(ciconinfo + 1) + coloroff;
00345 if(ciconinfo->bBitsPerPixel <= 8) {
00346 src += colorsize;
00347 }
00348 if(ciconinfo->bBitsPerPixel <= 8) {
00349 memcpy(&pInfo->bmiColors[0], (char *)(ciconinfo + 1) + coloroff, colorsize);
00350 }
00351
00352
00353 iconinfo->hbmColor = CreateDIBitmap(hdc, &pInfo->bmiHeader, CBM_INIT, src, pInfo, DIB_RGB_COLORS);
00354
00355 free(pInfo);
00356 DeleteDC(hdc);
00357 }
00358 else {
00359 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
00360 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
00361 (char *)(ciconinfo + 1)
00362 + ciconinfo->nHeight *
00363 BITMAP_GetWidthBytes (ciconinfo->nWidth, 1) );
00364 }
00365
00366 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
00367 1, 1, (char *)(ciconinfo + 1));
00368
00369 GlobalUnlock(hIcon);
00370
00371 return TRUE;
00372 }
00373
00374
00375 HCURSOR WIN32API CreateCursor(HINSTANCE hInst, int xHotSpot, int yHotSpot, int nWidth, int nHeight,
00376 const VOID *lpANDbits, const VOID *lpXORbits)
00377 {
00378 CURSORICONINFO info;
00379
00380 dprintf(("CreateCursor %dx%d spot=%d,%d xor=%p and=%p\n",
00381 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits));
00382
00383 info.ptHotSpot.x = xHotSpot;
00384 info.ptHotSpot.y = yHotSpot;
00385 info.nWidth = nWidth;
00386 info.nHeight = nHeight;
00387 info.nWidthBytes = 0;
00388 info.bPlanes = 1;
00389 info.bBitsPerPixel = 1;
00390 info.hInstance = hInst;
00391 info.dwResGroupId = -1;
00392 info.hColorBmp = 0;
00393
00394 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits, FALSE);
00395 }
00396
00397
00398 BOOL WIN32API DestroyCursor( HCURSOR hCursor)
00399 {
00400 dprintf(("USER32: DestroyCursor %x", hCursor));
00401 return CURSORICON_Destroy( hCursor, CID_WIN32 );
00402 }
00403
00404
00405 HCURSOR WIN32API GetCursor(void)
00406 {
00407 dprintf2(("USER32: GetCursor"));
00408 if(hActiveCursorPM && hActiveCursorPM != OSLibWinQueryPointer()) {
00409 dprintf(("Another app changed mouse cursor"));
00410 hActiveCursorPM = hActiveCursor = 0;
00411 }
00412 return hActiveCursor;
00413 }
00414
00415
00416 HCURSOR WIN32API SetCursor( HCURSOR hCursor)
00417 {
00418 HCURSOR hOldCursor;
00419
00420 dprintf(("USER32: SetCursor %x (prev %x)", hCursor, hActiveCursor));
00421 GetCursor();
00422 if (hCursor == hActiveCursor) return hActiveCursor;
00423
00424 hOldCursor = hActiveCursor;
00425 hActiveCursor = hCursor;
00426
00427 #ifdef __WIN32OS2__
00428 hCursor = ObjGetHandleData(hCursor, USEROBJ_CURSORICON);
00429 if(hCursor == -1) {
00430 dprintf(("ERROR: Invalid cursor/icon!"));
00431 return 0;
00432 }
00433 #endif
00434
00435 CURSORICONINFO *iconinfo = (CURSORICONINFO *)GlobalLock((HGLOBAL)hCursor);
00436 if (!iconinfo) {
00437 dprintf(("ERROR: Invalid cursor!"));
00438 return 0;
00439 }
00440 if(!iconinfo->hColorBmp) {
00441 dprintf(("SetCursor: invalid os/2 pointer handle!!"));
00442 }
00443
00444 dprintf2(("OSLibWinSetPointer %x", iconinfo->hColorBmp));
00445 if(OSLibWinSetPointer(iconinfo->hColorBmp) == FALSE) {
00446 dprintf(("OSLibWinSetPointer %x returned FALSE!!", iconinfo->hColorBmp));
00447 }
00448 hActiveCursorPM = iconinfo->hColorBmp;
00449 GlobalUnlock(hCursor);
00450
00451 return hOldCursor;
00452 }
00453
00454
00455 BOOL WIN32API GetCursorPos( PPOINT lpPoint)
00456 {
00457 dprintf2(("USER32: GetCursorPos %x", lpPoint));
00458
00459 if (!lpPoint) return FALSE;
00460
00461 if (OSLibWinQueryPointerPos(lpPoint))
00462 {
00463 mapScreenPoint((OSLIBPOINT*)lpPoint);
00464 return TRUE;
00465 }
00466 else return FALSE;
00467 }
00468
00469
00470 BOOL WIN32API SetCursorPos( int X, int Y)
00471 {
00472 dprintf(("USER32: SetCursorPos %d %d", X,Y));
00473 return OSLibWinSetPointerPos(X, mapScreenY(Y));
00474 }
00475
00476
00477 BOOL WIN32API ClipCursor(const RECT * lpRect)
00478 {
00479 if(lpRect) {
00480 dprintf(("USER32: ClipCursor (%d,%d)(%d,%d)", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom));
00481 }
00482 else dprintf(("USER32: ClipCursor NULL"));
00483 return OSLibWinClipCursor(lpRect);
00484 }
00485
00486
00487 BOOL WIN32API GetClipCursor( LPRECT lpRect)
00488 {
00489 dprintf(("USER32: GetClipCursor %x", lpRect));
00490 return OSLibWinGetClipCursor(lpRect);
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 BOOL WIN32API SetSystemCursor(HCURSOR hCursor, DWORD dwCursorId)
00513 {
00514 dprintf(("USER32:SetSystemCursor (%08xh,%08x) not supported.\n",
00515 hCursor,
00516 dwCursorId));
00517
00518 return DestroyCursor(hCursor);
00519 }
00520
00521
00522 INT OPEN32API __ShowCursor(BOOL bShow);
00523
00524 inline INT _ShowCursor (BOOL bShow)
00525 {
00526 INT yyrc;
00527 USHORT sel = RestoreOS2FS();
00528
00529 yyrc = __ShowCursor(bShow);
00530 SetFS(sel);
00531
00532 return yyrc;
00533 }
00534
00535 static int cursorshowcnt = 0;
00536
00537 void RestoreCursor()
00538 {
00539 dprintf2(("USER32: RestoreCursor %d", cursorshowcnt));
00540 while(cursorshowcnt != 0)
00541 {
00542 if(cursorshowcnt > 0 )
00543 {
00544 ShowCursor(FALSE);
00545 }
00546 else
00547 {
00548 ShowCursor(TRUE);
00549 }
00550 }
00551 }
00552
00553
00554 int WIN32API ShowCursor(BOOL bShow)
00555 {
00556 dprintf2(("USER32: ShowCursor %d", bShow));
00557 cursorshowcnt = cursorshowcnt + ((bShow) ? 1 : -1);
00558 return _ShowCursor(bShow);
00559 }
00560
00561
00562
00563 static HGLOBAL CreateCursorIconIndirect( HINSTANCE hInstance,
00564 CURSORICONINFO *info,
00565 LPCVOID lpANDbits,
00566 LPCVOID lpXORbits, BOOL fIcon)
00567 {
00568 HGLOBAL handle;
00569 char *ptr;
00570 int sizeAnd, sizeXor;
00571 #ifdef __WIN32OS2__
00572 BITMAP bmpXor, bmpAnd;
00573 #endif
00574
00575 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
00576 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
00577 sizeXor = info->nHeight * info->nWidthBytes;
00578 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
00579 if (!(handle = GlobalAlloc( GMEM_MOVEABLE,
00580 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
00581 return 0;
00582 ptr = (char *)GlobalLock( handle );
00583 memcpy( ptr, info, sizeof(*info) );
00584 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
00585 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
00586 #ifdef __WIN32OS2__
00587 bmpAnd.bmType = 0;
00588 bmpAnd.bmWidth = info->nWidth;
00589 bmpAnd.bmHeight = info->nHeight;
00590 bmpAnd.bmWidthBytes = BITMAP_GetWidthBytes(info->nWidth, 1);
00591 bmpAnd.bmPlanes = info->bPlanes;
00592 bmpAnd.bmBitsPixel = 1;
00593 bmpAnd.bmBits = NULL;
00594
00595 bmpXor.bmType = 0;
00596 bmpXor.bmWidth = info->nWidth;
00597 bmpXor.bmHeight = info->nHeight;
00598 bmpXor.bmWidthBytes = info->nWidthBytes;
00599 bmpXor.bmPlanes = info->bPlanes;
00600 bmpXor.bmBitsPixel = info->bBitsPerPixel;
00601 bmpXor.bmBits = NULL;
00602 ((CURSORICONINFO *)ptr)->hColorBmp =
00603 OSLibWinCreatePointer(info, (char *)lpANDbits, (LPBITMAP_W)&bmpAnd, (char *)lpXORbits, (LPBITMAP_W)&bmpXor, fIcon == FALSE);
00604 #endif
00605 GlobalUnlock( handle );
00606
00607 #ifdef __WIN32OS2__
00608 HICON hIcon;
00609 if(ObjAllocateHandle(&hIcon, (DWORD)handle, USEROBJ_CURSORICON) == FALSE) {
00610 GlobalFree(handle);
00611 dprintf(("ERROR: CreateCursorIconIndirect ObjAllocateHandle failed!!"));
00612 return 0;
00613 }
00614 dprintf(("USER32: CreateCursorIconIndirect returned %x", hIcon));
00615 return hIcon;
00616 #else
00617 return handle;
00618 #endif
00619 }
00620
00621
00622
00623
00624
00625 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
00626 INT width, INT height, INT colors,
00627 BOOL fCursor, UINT loadflags )
00628 {
00629 HANDLE handle = 0, h = 0;
00630 HANDLE hRsrc;
00631 CURSORICONDIR *dir;
00632 CURSORICONDIRENTRY *dirEntry;
00633 LPBYTE bits;
00634
00635 #ifdef __WIN32OS2__
00636
00637 if (fCursor && hInstance == NULL && !HIWORD(name))
00638 {
00639 HCURSOR hCursor = OSLibWinQuerySysPointer((ULONG)name, width, height);
00640 if(hCursor)
00641 {
00642
00643 if ((loadflags & LR_SHARED)
00644 && (h = CURSORICON_FindSharedIcon( -1, hCursor ) ) != 0 )
00645 {
00646 dprintf(("Found icon/cursor in cache; returned old handle %x", h));
00647 return h;
00648 }
00649
00650 HANDLE hObj = GlobalAlloc( GMEM_MOVEABLE, sizeof(CURSORICONINFO));
00651 if (!hObj)
00652 {
00653 DebugInt3();
00654 return 0;
00655 }
00656 CURSORICONINFO *info;
00657
00658 info = (CURSORICONINFO *)GlobalLock( hObj );
00659 info->ptHotSpot.x = 0;
00660 info->ptHotSpot.y = 0;
00661 info->nWidth = width;
00662 info->nHeight = height;
00663 info->nWidthBytes = width*height/8;
00664 info->bPlanes = 1;
00665 info->bBitsPerPixel = 1;
00666 info->hColorBmp = hCursor;
00667 info->hInstance = -1;
00668 info->dwResGroupId = -1;
00669
00670 HICON hIcon;
00671 if(ObjAllocateHandle(&hIcon, (DWORD)hObj, USEROBJ_CURSORICON) == FALSE) {
00672 GlobalUnlock( hObj );
00673 GlobalFree(hObj);
00674 dprintf(("ERROR: CURSORICON_Load ObjAllocateHandle failed!!"));
00675 return 0;
00676 }
00677
00678 if (loadflags & LR_SHARED )
00679 CURSORICON_AddSharedIcon( -1, hCursor, -1, hIcon );
00680
00681 GlobalUnlock( hObj );
00682
00683 return hIcon;
00684 }
00685 }
00686 #endif
00687 if ( loadflags & LR_LOADFROMFILE )
00688 {
00689 LPBYTE *ptr;
00690
00691 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
00692 return 0;
00693 if (fCursor)
00694 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
00695 else
00696 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
00697 bits = ptr[dirEntry->wResId-1];
00698 h = CURSORICON_CreateFromResource( 0, -1, 0, bits, dirEntry->dwBytesInRes,
00699 !fCursor, 0x00030000, width, height, loadflags);
00700
00701 HeapFree( GetProcessHeap(), 0, dir );
00702 HeapFree( GetProcessHeap(), 0, ptr );
00703 }
00704 else
00705 {
00706 HANDLE hGroupRsrc;
00707 WORD wResId;
00708 DWORD dwBytesInRes;
00709 BOOL bIsGroup = TRUE;
00710
00711
00712 if (!hInstance)
00713 {
00714 hRsrc = FindResourceW(hInstanceUser32, name, fCursor ? RT_CURSORW : RT_ICONW);
00715 if(!hRsrc) {
00716 hRsrc = FindResourceW(hInstanceUser32, name, fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW);
00717 }
00718 else bIsGroup = FALSE;
00719
00720 if(!hRsrc) return 0;
00721
00722 hInstance = hInstanceUser32;
00723 }
00724 else {
00725 hRsrc = FindResourceW(hInstance, name, fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW);
00726 if(!hRsrc) return 0;
00727 }
00728 hGroupRsrc = hRsrc;
00729
00730 if(bIsGroup) {
00731
00732
00733 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
00734 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
00735
00736 if (fCursor)
00737 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
00738 width, height, 1);
00739 else
00740 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
00741 width, height, colors );
00742 if (!dirEntry) return 0;
00743 wResId = dirEntry->wResId;
00744 dwBytesInRes = dirEntry->dwBytesInRes;
00745 FreeResource( handle );
00746
00747
00748 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
00749 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
00750 }
00751
00752
00753 if ((loadflags & LR_SHARED)
00754 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
00755 {
00756 dprintf(("Found icon/cursor in cache; returned old handle %x", h));
00757 return h;
00758 }
00759
00760 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
00761 bits = (LPBYTE)LockResource( handle );
00762 h = CURSORICON_CreateFromResource( hInstance, (DWORD)name, 0, bits, dwBytesInRes,
00763 !fCursor, 0x00030000, width, height, loadflags);
00764 FreeResource( handle );
00765
00766
00767
00768 if ( h && (loadflags & LR_SHARED) )
00769 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
00770
00771 }
00772
00773 return h;
00774 }
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
00787 CURSORICONDIR **res, LPBYTE **ptr)
00788 {
00789 LPBYTE _free;
00790 CURSORICONFILEDIR *bits;
00791 int entries, size, i;
00792 HANDLE hMapping = 0;
00793
00794 *res = NULL;
00795 *ptr = NULL;
00796
00797 hMapping = VIRTUAL_MapFileW( filename, (LPVOID *)&bits, TRUE);
00798 if(hMapping == INVALID_HANDLE_VALUE)
00799 return FALSE;
00800
00801
00802
00803
00804 if ( *(LPDWORD)bits==0x46464952 )
00805 {
00806 LPBYTE pos = (LPBYTE) bits;
00807 dprintf(("Animated icons not correctly implemented! %p \n", bits));
00808
00809 for (;;)
00810 {
00811 if (*(LPDWORD)pos==0x6e6f6369)
00812 {
00813 dprintf(("icon entry found! %p\n", bits));
00814 pos+=4;
00815 if ( !*(LPWORD) pos==0x2fe)
00816 {
00817 goto fail;
00818 }
00819 bits=(CURSORICONFILEDIR*)(pos+4);
00820 dprintf(("icon size ok. offset=%p \n", bits));
00821 break;
00822 }
00823 pos+=2;
00824 if (pos>=(LPBYTE)bits+766) goto fail;
00825 }
00826 }
00827 if (!(entries = bits->idCount)) goto fail;
00828 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
00829 _free = (LPBYTE) size;
00830
00831 for (i=0; i < entries; i++)
00832 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
00833
00834 if (!(*ptr = (LPBYTE *)HeapAlloc( GetProcessHeap(), 0,
00835 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
00836 if (!(*res = (CURSORICONDIR *)HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
00837
00838 _free = (LPBYTE)(*res) + (int)_free;
00839 memcpy((*res), bits, 6);
00840 for (i=0; i<entries; i++)
00841 {
00842 ((LPBYTE*)(*ptr))[i] = _free;
00843 if (fCursor) {
00844 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
00845 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
00846 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
00847 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
00848 _free+=sizeof(POINT16);
00849 }
00850 else {
00851 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
00852 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
00853 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
00854 }
00855 (*res)->idEntries[i].wPlanes=1;
00856 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
00857 bits->idEntries[i].dwDIBOffset))->biBitCount;
00858 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
00859 (*res)->idEntries[i].wResId=i+1;
00860
00861 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
00862 (*res)->idEntries[i].dwBytesInRes);
00863 _free += (*res)->idEntries[i].dwBytesInRes;
00864 }
00865 UnmapViewOfFile( bits );
00866 CloseHandle(hMapping);
00867 return TRUE;
00868
00869 fail:
00870 if (*res) HeapFree( GetProcessHeap(), 0, *res );
00871 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
00872
00873 UnmapViewOfFile( bits );
00874 CloseHandle(hMapping);
00875 return FALSE;
00876 }
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886 static HGLOBAL CURSORICON_CreateFromResource( HINSTANCE hInstance, DWORD dwResGroupId, HGLOBAL hObj, LPBYTE bits,
00887 UINT cbSize, BOOL bIcon, DWORD dwVersion,
00888 INT width, INT height, UINT loadflags )
00889 {
00890 int sizeAnd, sizeXor;
00891 HBITMAP hAndBits = 0, hXorBits = 0;
00892 BITMAP bmpXor, bmpAnd;
00893 POINT16 hotspot;
00894 BITMAPINFO *bmi;
00895 HDC hdc = 0;
00896 BOOL DoStretch;
00897 INT size, colortablesize, bwsize, colorsize;
00898
00899 hotspot.x = ICON_HOTSPOT;
00900 hotspot.y = ICON_HOTSPOT;
00901
00902 dprintf2(("CURSORICON_CreateFromResource %x %x %x %x %d", hInstance, dwResGroupId, hObj, bits, cbSize));
00903
00904 if (dwVersion == 0x00020000)
00905 {
00906 dprintf(("CURSORICON_CreateFromResource 2.xx resources are not supported"));
00907 return 0;
00908 }
00909
00910 if (bIcon) {
00911 bmi = (BITMAPINFO *)bits;
00912 }
00913 else
00914 {
00915 POINT16 *pt = (POINT16 *)bits;
00916 hotspot = *pt;
00917 bmi = (BITMAPINFO *)(pt + 1);
00918 }
00919 size = DIB_BitmapInfoSize(bmi, DIB_RGB_COLORS);
00920
00921 if (!width) width = bmi->bmiHeader.biWidth;
00922 if (!height) height = bmi->bmiHeader.biHeight/2;
00923
00924 DoStretch = (bmi->bmiHeader.biHeight/2 != height) || (bmi->bmiHeader.biWidth != width);
00925
00926 colorsize = DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2, bmi->bmiHeader.biBitCount);
00927 bwsize = (bmi->bmiHeader.biWidth * bmi->bmiHeader.biHeight/2)/8;
00928
00929
00930 if((bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
00931 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
00932 bmi->bmiHeader.biCompression != BI_RGB) )
00933 {
00934 return 0;
00935 }
00936
00937 #ifdef __WIN32OS2__
00938 if( (hdc = CreateCompatibleDC( 0 )) )
00939 #else
00940 if( (hdc = GetDC( 0 )) )
00941 #endif
00942 {
00943 BITMAPINFO* pInfo;
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
00957 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
00958 {
00959 memcpy( pInfo, bmi, size );
00960 pInfo->bmiHeader.biHeight /= 2;
00961
00962
00963 if (DoStretch)
00964 {
00965 if(bIcon)
00966 {
00967 hXorBits = CreateCompatibleBitmap(hdc, width, height);
00968 }
00969 else
00970 {
00971 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
00972 }
00973 if(hXorBits)
00974 {
00975 HBITMAP hOld;
00976 HDC hMem = CreateCompatibleDC(hdc);
00977 BOOL res;
00978
00979 if (hMem) {
00980 hOld = SelectObject(hMem, hXorBits);
00981 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
00982 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
00983 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
00984 SelectObject(hMem, hOld);
00985 DeleteDC(hMem);
00986 }
00987 else res = FALSE;
00988 if (!res) {
00989 DeleteObject(hXorBits);
00990 hXorBits = 0;
00991 }
00992 }
00993 }
00994 else
00995 {
00996 hXorBits = CreateDIBitmap(hdc, &pInfo->bmiHeader,
00997 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
00998 }
00999 if( hXorBits )
01000 {
01001 char* xbits = (char *)bmi + size + DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
01002 bmi->bmiHeader.biHeight,
01003 bmi->bmiHeader.biBitCount) / 2;
01004
01005 pInfo->bmiHeader.biBitCount = 1;
01006 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
01007 {
01008 RGBQUAD *rgb = pInfo->bmiColors;
01009
01010 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
01011 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
01012 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
01013 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
01014 }
01015 else
01016 {
01017 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
01018
01019 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
01020 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
01021 }
01022
01023
01024 if (DoStretch)
01025 {
01026 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL)))
01027 {
01028 HBITMAP hOld;
01029 HDC hMem = CreateCompatibleDC(hdc);
01030 BOOL res;
01031
01032 if (hMem) {
01033 hOld = SelectObject(hMem, hAndBits);
01034
01035
01036 #if 1
01037 HBITMAP hBmp, hOld1;
01038 HDC hMem1;
01039
01040 hMem1 = CreateCompatibleDC(hdc);
01041
01042 int linewidth = BITMAP_GetWidthBytes(pInfo->bmiHeader.biWidth, 1);
01043
01044 char *newpix = (char *)malloc(linewidth*pInfo->bmiHeader.biHeight);
01045
01046 newpix += ((pInfo->bmiHeader.biHeight-1)*linewidth);
01047
01048 if(cbSize - size - colorsize - bwsize == bwsize)
01049 {
01050 for(int i=0;i<pInfo->bmiHeader.biHeight;i++) {
01051 memcpy(newpix, xbits, linewidth);
01052 newpix -= linewidth;
01053 xbits += linewidth*2;
01054 }
01055 }
01056 else {
01057 for(int i=0;i<pInfo->bmiHeader.biHeight;i++) {
01058 memcpy(newpix, xbits, linewidth);
01059 newpix -= linewidth;
01060 xbits += linewidth;
01061 }
01062 }
01063 newpix += linewidth;
01064 hBmp = CreateBitmap(pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight, 1, 1, newpix);
01065 free(newpix);
01066
01067 hOld1 = SelectObject(hMem1, hBmp);
01068
01069 res = StretchBlt(hMem, 0, 0, width, height, hMem1, 0, 0, pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight, SRCCOPY);
01070
01071 SelectObject(hMem1, hOld1);
01072 DeleteObject(hBmp);
01073 DeleteDC(hMem1);
01074
01075
01076 #else
01077 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
01078 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
01079 xbits, pInfo, DIB_RGB_COLORS, SRCCOPY);
01080 #endif
01081 SelectObject(hMem, hOld);
01082 DeleteDC(hMem);
01083 }
01084 else res = FALSE;
01085 if (!res) {
01086 DeleteObject(hAndBits);
01087 hAndBits = 0;
01088 }
01089 }
01090 }
01091 else {
01092
01093 #if 1
01094 int linewidth = BITMAP_GetWidthBytes(width, 1);
01095
01096 char *newpix = (char *)malloc(linewidth*height);
01097
01098 newpix += ((height-1)*linewidth);
01099
01100 if(cbSize - size - colorsize - bwsize == bwsize)
01101 {
01102 for(int i=0;i<height;i++) {
01103 memcpy(newpix, xbits, linewidth);
01104 newpix -= linewidth;
01105 xbits += linewidth*2;
01106 }
01107 }
01108 else {
01109 for(int i=0;i<height;i++) {
01110 memcpy(newpix, xbits, linewidth);
01111 newpix -= linewidth;
01112 xbits += linewidth;
01113 }
01114 }
01115 newpix += linewidth;
01116 hAndBits = CreateBitmap(width, height, 1, 1, newpix);
01117
01118 free(newpix);
01119
01120 #else
01121 hAndBits = CreateDIBitmap(hdc, &pInfo->bmiHeader,
01122 CBM_INIT, xbits, pInfo, DIB_RGB_COLORS );
01123 #endif
01124 }
01125 if( !hAndBits )
01126 DeleteObject( hXorBits );
01127 }
01128 HeapFree( GetProcessHeap(), 0, pInfo );
01129 }
01130 #ifdef __WIN32OS2__
01131 DeleteDC(hdc );
01132 #else
01133 ReleaseDC( 0, hdc );
01134 #endif
01135 }
01136
01137 if( !hXorBits || !hAndBits )
01138 {
01139 dprintf(("\tunable to create an icon bitmap."));
01140 return 0;
01141 }
01142
01143
01144 GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor );
01145 GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd );
01146 colortablesize = 0;
01147
01148 if(bmpXor.bmBitsPixel <= 8) {
01149 colortablesize = sizeof(RGBQUAD)*(1<<bmpXor.bmBitsPixel);
01150 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes + colortablesize;
01151 }
01152 else sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
01153
01154 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
01155
01156 if (hObj) hObj = GlobalReAlloc( hObj,
01157 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
01158 if (!hObj) hObj = GlobalAlloc( GMEM_MOVEABLE,
01159 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
01160 if (hObj)
01161 {
01162 CURSORICONINFO *info;
01163
01164 info = (CURSORICONINFO *)GlobalLock( hObj );
01165 info->ptHotSpot.x = hotspot.x;
01166 info->ptHotSpot.y = hotspot.y;
01167 info->nWidth = bmpXor.bmWidth;
01168 info->nHeight = bmpXor.bmHeight;
01169 info->nWidthBytes = bmpXor.bmWidthBytes;
01170 info->bPlanes = bmpXor.bmPlanes;
01171 info->bBitsPerPixel = bmpXor.bmBitsPixel;
01172 info->hInstance = hInstance;
01173 info->dwResGroupId = dwResGroupId;
01174 info->hColorBmp = 0;
01175
01176
01177 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1));
01178
01179 if(bmpXor.bmBitsPixel > 1)
01180 {
01181 BITMAPINFO* pInfo = (BITMAPINFO *)malloc(sizeof(BITMAPINFO)+colortablesize+3*sizeof(DWORD));
01182 HBITMAP oldbmp;
01183
01184 hdc = CreateCompatibleDC(0);
01185
01186 memset(pInfo, 0, sizeof(BITMAPINFO)+colortablesize+3*sizeof(DWORD));
01187 pInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
01188 pInfo->bmiHeader.biPlanes = info->bPlanes;
01189 pInfo->bmiHeader.biBitCount = info->bBitsPerPixel;
01190
01191 GetDIBits(hdc, hXorBits, 0, bmpXor.bmHeight, (char *)(info + 1) + sizeAnd + colortablesize, pInfo, DIB_RGB_COLORS);
01192 if(colortablesize) {
01193 memcpy((char *)(info + 1) + sizeAnd, (char *)&pInfo->bmiHeader + pInfo->bmiHeader.biSize, colortablesize);
01194 }
01195
01196 DeleteDC(hdc);
01197 free(pInfo);
01198 }
01199 else {
01200 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd);
01201 }
01202 info->hColorBmp = OSLibWinCreatePointer(info, (char*)(info + 1), (LPBITMAP_W)&bmpAnd, (char*)(info + 1) + sizeAnd, (LPBITMAP_W)&bmpXor, bIcon == FALSE);
01203
01204 dprintf(("Create cursor/icon %x with OS/2 pointer handle %x", hObj, info->hColorBmp));
01205 GlobalUnlock( hObj );
01206 }
01207
01208 DeleteObject( hAndBits );
01209 DeleteObject( hXorBits );
01210
01211 #ifdef __WIN32OS2__
01212 if(hObj) {
01213 HICON hIcon;
01214 if(ObjAllocateHandle(&hIcon, (DWORD)hObj, USEROBJ_CURSORICON) == FALSE) {
01215 GlobalFree(hObj);
01216 dprintf(("ERROR: CURSORICON_Load ObjAllocateHandle failed!!"));
01217 return 0;
01218 }
01219 return hIcon;
01220 }
01221 #endif
01222 return hObj;
01223 }
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233 WORD WIN32API CURSORICON_Destroy( HGLOBAL handle, UINT flags )
01234 {
01235 WORD retv;
01236
01237
01238
01239 if ( hActiveCursor == handle )
01240 {
01241 dprintf(("WARNING: Destroying active cursor!" ));
01242 SetCursor( 0 );
01243 }
01244
01245 #ifdef __WIN32OS2__
01246 HICON hIcon = ObjGetHandleData(handle, USEROBJ_CURSORICON);
01247 if(hIcon == -1) {
01248 dprintf(("ERROR: Invalid cursor/icon!"));
01249 return 0;
01250 }
01251 #endif
01252
01253
01254 if ( !(flags & CID_NONSHARED) )
01255 {
01256 INT count = CURSORICON_DelSharedIcon( handle );
01257
01258 if ( count != -1 )
01259 return (flags & CID_WIN32)? TRUE : (count == 0);
01260
01261
01262 }
01263
01264
01265 #ifdef __WIN32OS2__
01266 CURSORICONINFO *iconinfo = (CURSORICONINFO *)GlobalLock((HGLOBAL)hIcon);
01267 if (!iconinfo) {
01268 dprintf(("ERROR: Invalid cursor!"));
01269 return 0;
01270 }
01271
01272 if(iconinfo->hColorBmp) {
01273 OSLibWinDestroyPointer(iconinfo->hColorBmp);
01274 }
01275 GlobalUnlock(hIcon);
01276 retv = GlobalFree( hIcon );
01277 ObjFreeHandle(handle);
01278
01279 return (flags & CID_RESOURCE)? retv : TRUE;
01280 #else
01281 retv = GlobalFree( handle );
01282 return (flags & CID_RESOURCE)? retv : TRUE;
01283 #endif
01284 }
01285
01286
01287
01288
01289
01290
01291 static HGLOBAL CURSORICON_Copy(HGLOBAL handle)
01292 {
01293 char *ptrOld, *ptrNew;
01294 int size;
01295 HGLOBAL hNew;
01296
01297 handle = ObjGetHandleData(handle, USEROBJ_CURSORICON);
01298 if(handle == -1) {
01299 dprintf(("ERROR: Invalid cursor/icon!"));
01300 return 0;
01301 }
01302
01303 if (!(ptrOld = (char *)GlobalLock( handle ))) return 0;
01304
01305 size = GlobalSize( handle );
01306 hNew = GlobalAlloc( GMEM_MOVEABLE, size );
01307 #ifdef __WIN32OS2__
01308 if(hNew == NULL) {
01309 dprintf(("ERROR: CURSORICON_Copy GlobalAlloc failed!!"));
01310 return NULL;
01311 }
01312 #endif
01313 ptrNew = (char *)GlobalLock( hNew );
01314 memcpy( ptrNew, ptrOld, size );
01315 GlobalUnlock( handle );
01316 GlobalUnlock( hNew );
01317
01318 #ifdef __WIN32OS2__
01319 HICON hIcon;
01320 if(ObjAllocateHandle(&hIcon, (DWORD)hNew, USEROBJ_CURSORICON) == FALSE) {
01321 GlobalFree(hNew);
01322 dprintf(("ERROR: CURSORICON_Copy ObjAllocateHandle failed!!"));
01323 return 0;
01324 }
01325 return hIcon;
01326 #else
01327 return hNew;
01328 #endif
01329 }
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
01354 INT iDesiredCX, INT iDesiredCY,
01355 UINT nFlags)
01356 {
01357 HGLOBAL hNew=0;
01358
01359 #ifdef __WIN32OS2__
01360 HICON hIcon = ObjGetHandleData(Handle, USEROBJ_CURSORICON);
01361 if(hIcon == -1) {
01362 dprintf(("ERROR: Invalid cursor/icon!"));
01363 return 0;
01364 }
01365
01366 #else
01367 if(Handle == 0)
01368 {
01369 return 0;
01370 }
01371 #endif
01372
01373 if( (nFlags & LR_COPYFROMRESOURCE
01374 && (iDesiredCX > 0 || iDesiredCY > 0))
01375 || nFlags & LR_MONOCHROME)
01376 {
01377 #ifdef __WIN32OS2__
01378 ICONCACHE* pIconCache = CURSORICON_FindCache(hIcon);
01379 #else
01380 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
01381 #endif
01382
01383
01384
01385 if(pIconCache == NULL)
01386 {
01387 #ifdef __WIN32OS2__
01388 hNew = CURSORICON_Copy(Handle);
01389 #else
01390 hNew = CURSORICON_Copy(0, Handle);
01391 #endif
01392 if(nFlags & LR_COPYFROMRESOURCE)
01393 {
01394 dprintf(("WARNING: LR_COPYFROMRESOURCE: Failed to load from cache\n"));
01395 }
01396 }
01397 else
01398 {
01399 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
01400 LPBYTE pBits;
01401 HANDLE hMem;
01402 HRSRC hRsrc;
01403 DWORD dwBytesInRes;
01404 WORD wResId;
01405 DWORD dwResGroupId;
01406 HINSTANCE hInstance;
01407 CURSORICONINFO *iconinfo;
01408 CURSORICONDIR *pDir;
01409 CURSORICONDIRENTRY *pDirEntry;
01410 BOOL bIsIcon = (nType == IMAGE_ICON);
01411
01412 #ifdef __WIN32OS2__
01413 iconinfo = (CURSORICONINFO *)GlobalLock( hIcon );
01414 #else
01415 iconinfo = (CURSORICONINFO *)GlobalLock( Handle );
01416 #endif
01417 if(iconinfo == NULL) {
01418 dprintf(("ERROR: CURSORICON_ExtCopy invalid icon!"));
01419 }
01420 hInstance = iconinfo->hInstance;
01421 dwResGroupId = iconinfo->dwResGroupId;
01422 GlobalUnlock( Handle );
01423 if(dwResGroupId == -1) {
01424
01425 dprintf(("WARNING: no resource associated with icon/cursor -> copy without scaling!"));
01426 hNew = CURSORICON_Copy(Handle);
01427 return hNew;
01428 }
01429
01430
01431
01432 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
01433 || (iDesiredCX == 0 && iDesiredCY == 0))
01434 {
01435 iDesiredCY = GetSystemMetrics(bIsIcon ? SM_CYICON : SM_CYCURSOR);
01436 iDesiredCX = GetSystemMetrics(bIsIcon ? SM_CXICON : SM_CXCURSOR);
01437 }
01438
01439
01440
01441 hRsrc = FindResourceW(hInstance, (LPWSTR)dwResGroupId, bIsIcon ? RT_GROUP_ICONW : RT_GROUP_CURSORW);
01442 if(!hRsrc) {
01443 goto notfound;
01444 }
01445
01446 if (!(hMem = LoadResource( hInstance, hRsrc)))
01447 {
01448 goto notfound;
01449 }
01450 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
01451 {
01452 goto notfound;
01453 }
01454
01455
01456
01457 if(bIsIcon)
01458 {
01459 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
01460 pDir, iDesiredCX, iDesiredCY, 256);
01461 }
01462 else
01463 {
01464 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
01465 pDir, iDesiredCX, iDesiredCY, 1);
01466 }
01467
01468 wResId = pDirEntry->wResId;
01469 dwBytesInRes = pDirEntry->dwBytesInRes;
01470 FreeResource(hMem);
01471
01472
01473
01474 if (!(hRsrc = FindResourceW(hInstance ,
01475 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
01476 {
01477 goto notfound;
01478 }
01479 if (!(hMem = LoadResource( hInstance, hRsrc )))
01480 {
01481 goto notfound;
01482 }
01483
01484 pBits = (LPBYTE)LockResource( hMem );
01485
01486 if(nFlags & LR_DEFAULTSIZE)
01487 {
01488 iTargetCY = GetSystemMetrics(SM_CYICON);
01489 iTargetCX = GetSystemMetrics(SM_CXICON);
01490 }
01491
01492
01493
01494 hNew = CURSORICON_CreateFromResource( hInstance, dwResGroupId, 0, pBits, dwBytesInRes,
01495 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
01496 FreeResource(hMem);
01497 }
01498 }
01499 else
01500 {
01501 hNew = CURSORICON_Copy(Handle);
01502 }
01503 return hNew;
01504
01505 notfound:
01506 dprintf(("WARNING: unable to find resource associated with icon/cursor -> copy without scaling!"));
01507 hNew = CURSORICON_Copy(Handle);
01508 return hNew;
01509 }
01510
01511
01512
01513
01514
01515
01516 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
01517 int height, int colors )
01518 {
01519 int i;
01520 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
01521 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
01522 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
01523
01524 if (dir->idCount < 1)
01525 {
01526 dprintf(("Empty directory!\n" ));
01527 return NULL;
01528 }
01529 if (dir->idCount == 1) return &dir->idEntries[0];
01530
01531
01532 iTotalDiff = 0xFFFFFFFF;
01533 iColorDiff = 0xFFFFFFFF;
01534 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
01535 {
01536 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
01537 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
01538
01539 if(iTotalDiff > (iTempXDiff + iTempYDiff))
01540 {
01541 iXDiff = iTempXDiff;
01542 iYDiff = iTempYDiff;
01543 iTotalDiff = iXDiff + iYDiff;
01544 }
01545 }
01546
01547
01548 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
01549 {
01550 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
01551 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
01552 {
01553 #ifdef __WIN32OS2__
01554 iTempColorDiff = abs(colors - (1 << entry->wBitCount));
01555 #else
01556 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
01557 #endif
01558 if(iColorDiff > iTempColorDiff)
01559 {
01560 bestEntry = entry;
01561 iColorDiff = iTempColorDiff;
01562 }
01563 }
01564 }
01565
01566 dprintf(("CURSORICON_FindBestIcon (%d,%d) %d -> %d", width, height, colors, (bestEntry) ? bestEntry->wResId : 0));
01567 return bestEntry;
01568 }
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
01579 int width, int height, int color)
01580 {
01581 int i, maxwidth, maxheight;
01582 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
01583
01584 if (dir->idCount < 1)
01585 {
01586 dprintf(("Empty directory!\n" ));
01587 return NULL;
01588 }
01589 if (dir->idCount == 1) return &dir->idEntries[0];
01590
01591
01592
01593 height *= 2;
01594
01595
01596
01597 maxwidth = maxheight = 0;
01598 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
01599 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
01600 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
01601 (entry->wBitCount == 1))
01602 {
01603 bestEntry = entry;
01604 maxwidth = entry->ResInfo.cursor.wWidth;
01605 maxheight = entry->ResInfo.cursor.wHeight;
01606 }
01607 if (bestEntry) return bestEntry;
01608
01609
01610
01611 maxwidth = maxheight = 255;
01612 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
01613 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
01614 (entry->wBitCount == 1))
01615 {
01616 bestEntry = entry;
01617 maxwidth = entry->ResInfo.cursor.wWidth;
01618 maxheight = entry->ResInfo.cursor.wHeight;
01619 }
01620
01621 return bestEntry;
01622 }
01623
01624
01625
01626
01627
01628 INT WIN32API LookupIconIdFromDirectoryEx(LPBYTE xdir, BOOL bIcon,
01629 INT width, INT height, UINT cFlag )
01630 {
01631 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
01632 UINT retVal = 0;
01633
01634 dprintf(("LookupIconIdFromDirectoryEx %x %d (%d,%d)", xdir, bIcon, width, height));
01635 if( dir && !dir->idReserved && (dir->idType & 3) )
01636 {
01637 CURSORICONDIRENTRY* entry;
01638 HDC hdc;
01639 UINT palEnts;
01640 int colors;
01641 hdc = GetDC(0);
01642 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
01643 if (palEnts == 0)
01644 palEnts = 256;
01645 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
01646
01647 ReleaseDC(0, hdc);
01648
01649 if( bIcon )
01650 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
01651 else
01652 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
01653
01654 if( entry ) retVal = entry->wResId;
01655 }
01656 else dprintf(("invalid resource directory\n"));
01657 return retVal;
01658 }
01659
01660
01661
01662 INT WIN32API LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
01663 {
01664 return LookupIconIdFromDirectoryEx( dir, bIcon,
01665 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
01666 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
01667 }
01668
01669
01670
01671
01672
01673
01674
01675
01676 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
01677 {
01678 HANDLE handle = 0;
01679 ICONCACHE *ptr;
01680
01681 EnterCriticalSection( &IconCrst );
01682
01683 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
01684 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
01685 {
01686 ptr->count++;
01687 handle = ptr->handle;
01688 break;
01689 }
01690
01691 LeaveCriticalSection( &IconCrst );
01692
01693 return handle;
01694 }
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
01710 {
01711 ICONCACHE *ptr;
01712 ICONCACHE *pRet=NULL;
01713 BOOL IsFound = FALSE;
01714 int count;
01715
01716 EnterCriticalSection( &IconCrst );
01717
01718 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
01719 {
01720 if ( handle == ptr->handle )
01721 {
01722 IsFound = TRUE;
01723 pRet = ptr;
01724 }
01725 }
01726
01727 LeaveCriticalSection( &IconCrst );
01728
01729 return pRet;
01730 }
01731
01732
01733
01734
01735 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
01736 {
01737 ICONCACHE *ptr = (ICONCACHE *)HeapAlloc( GetProcessHeap(), 0, sizeof(ICONCACHE) );
01738 if ( !ptr ) return;
01739
01740 ptr->hModule = hModule;
01741 ptr->hRsrc = hRsrc;
01742 ptr->handle = handle;
01743 ptr->hGroupRsrc = hGroupRsrc;
01744 ptr->count = 1;
01745
01746 EnterCriticalSection( &IconCrst );
01747 ptr->next = IconAnchor;
01748 IconAnchor = ptr;
01749 LeaveCriticalSection( &IconCrst );
01750 }
01751
01752
01753
01754
01755 static INT CURSORICON_DelSharedIcon( HANDLE handle )
01756 {
01757 INT count = -1;
01758 ICONCACHE *ptr;
01759
01760 EnterCriticalSection( &IconCrst );
01761
01762 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
01763 if ( ptr->handle == handle )
01764 {
01765 if ( ptr->count > 0 ) ptr->count--;
01766 count = ptr->count;
01767 break;
01768 }
01769
01770 LeaveCriticalSection( &IconCrst );
01771
01772 return count;
01773 }
01774
01775
01776
01777
01778 void CURSORICON_FreeModuleIcons( HMODULE hModule )
01779 {
01780 ICONCACHE **ptr = &IconAnchor;
01781
01782 EnterCriticalSection( &IconCrst );
01783
01784 while ( *ptr )
01785 {
01786 if ( (*ptr)->hModule == hModule )
01787 {
01788 ICONCACHE *freePtr = *ptr;
01789 *ptr = freePtr->next;
01790
01791 #ifdef __WIN32OS2__
01792 CURSORICON_Destroy(freePtr->handle, CID_NONSHARED);
01793 #else
01794 GlobalFree( freePtr->handle );
01795 #endif
01796 HeapFree( GetProcessHeap(), 0, freePtr );
01797 continue;
01798 }
01799 ptr = &(*ptr)->next;
01800 }
01801
01802 LeaveCriticalSection( &IconCrst );
01803 }
01804