2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
5 * 1996 Martin Von Loewis
7 * 1998 Turchanov Sergey
13 * http://www.microsoft.com/win32dev/ui/icons.htm
15 * Cursors and icons are stored in a global heap block, with the
18 * CURSORICONINFO info;
22 * The bits structures are in the format of a device-dependent bitmap.
24 * This layout is very sub-optimal, as the bitmap bits are stored in
25 * the X client instead of in the server like other bitmaps; however,
26 * some programs (notably Paint Brush) expect to be able to manipulate
27 * the bits directly :-(
29 * FIXME: what are we going to do with animation and color (bpp > 1) cursors ?!
37 #include "wine/winbase16.h"
38 #include "wine/winuser16.h"
42 #include "cursoricon.h"
44 #include "debugtools.h"
51 DECLARE_DEBUG_CHANNEL(cursor);
52 DECLARE_DEBUG_CHANNEL(icon);
53 DECLARE_DEBUG_CHANNEL(resource);
55 static HCURSOR hActiveCursor = 0; /* Active cursor */
56 static INT CURSOR_ShowCount = 0; /* Cursor display count */
57 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
60 /**********************************************************************
61 * ICONCACHE for cursors/icons loaded with LR_SHARED.
63 * FIXME: This should not be allocated on the system heap, but on a
64 * subsystem-global heap (i.e. one for all Win16 processes,
65 * and one each for every Win32 process).
67 typedef struct tagICONCACHE
69 struct tagICONCACHE *next;
80 static ICONCACHE *IconAnchor = NULL;
81 static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT;
82 static WORD ICON_HOTSPOT = 0x4242;
85 /***********************************************************************
88 * Helper function to map a file to memory:
90 * [RETURN] ptr - pointer to mapped file
92 static void *map_fileW( LPCWSTR name )
94 HANDLE hFile, hMapping;
97 hFile = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL,
98 OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0 );
99 if (hFile != INVALID_HANDLE_VALUE)
101 hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
102 CloseHandle( hFile );
105 ptr = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
106 CloseHandle( hMapping );
113 /**********************************************************************
114 * CURSORICON_FindSharedIcon
116 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
121 EnterCriticalSection( &IconCrst );
123 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
124 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
127 handle = ptr->handle;
131 LeaveCriticalSection( &IconCrst );
136 /*************************************************************************
137 * CURSORICON_FindCache
139 * Given a handle, find the corresponding cache element
142 * Handle [I] handle to an Image
145 * Success: The cache entry
149 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
152 ICONCACHE *pRet=NULL;
153 BOOL IsFound = FALSE;
156 EnterCriticalSection( &IconCrst );
158 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
160 if ( handle == ptr->handle )
167 LeaveCriticalSection( &IconCrst );
172 /**********************************************************************
173 * CURSORICON_AddSharedIcon
175 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
177 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
180 ptr->hModule = hModule;
182 ptr->handle = handle;
183 ptr->hGroupRsrc = hGroupRsrc;
186 EnterCriticalSection( &IconCrst );
187 ptr->next = IconAnchor;
189 LeaveCriticalSection( &IconCrst );
192 /**********************************************************************
193 * CURSORICON_DelSharedIcon
195 static INT CURSORICON_DelSharedIcon( HANDLE handle )
200 EnterCriticalSection( &IconCrst );
202 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
203 if ( ptr->handle == handle )
205 if ( ptr->count > 0 ) ptr->count--;
210 LeaveCriticalSection( &IconCrst );
215 /**********************************************************************
216 * CURSORICON_FreeModuleIcons
218 void CURSORICON_FreeModuleIcons( HMODULE hModule )
220 ICONCACHE **ptr = &IconAnchor;
222 if ( HIWORD( hModule ) )
223 hModule = MapHModuleLS( hModule );
225 hModule = GetExePtr( hModule );
227 EnterCriticalSection( &IconCrst );
231 if ( (*ptr)->hModule == hModule )
233 ICONCACHE *freePtr = *ptr;
234 *ptr = freePtr->next;
236 GlobalFree16( freePtr->handle );
237 HeapFree( SystemHeap, 0, freePtr );
243 LeaveCriticalSection( &IconCrst );
246 /**********************************************************************
247 * CURSORICON_FindBestIcon
249 * Find the icon closest to the requested size and number of colors.
251 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
252 int height, int colors )
255 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
256 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
257 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
259 if (dir->idCount < 1)
261 WARN_(icon)("Empty directory!\n" );
264 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
267 iTotalDiff = 0xFFFFFFFF;
268 iColorDiff = 0xFFFFFFFF;
269 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
271 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
272 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
274 if(iTotalDiff > (iTempXDiff + iTempYDiff))
278 iTotalDiff = iXDiff + iYDiff;
282 /* Find Best Colors for Best Fit */
283 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
285 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
286 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
288 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
289 if(iColorDiff > iTempColorDiff)
292 iColorDiff = iTempColorDiff;
301 /**********************************************************************
302 * CURSORICON_FindBestCursor
304 * Find the cursor closest to the requested size.
305 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
308 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
309 int width, int height, int color)
311 int i, maxwidth, maxheight;
312 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
314 if (dir->idCount < 1)
316 WARN_(cursor)("Empty directory!\n" );
319 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
321 /* Double height to account for AND and XOR masks */
325 /* First find the largest one smaller than or equal to the requested size*/
327 maxwidth = maxheight = 0;
328 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
329 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
330 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
331 (entry->wBitCount == 1))
334 maxwidth = entry->ResInfo.cursor.wWidth;
335 maxheight = entry->ResInfo.cursor.wHeight;
337 if (bestEntry) return bestEntry;
339 /* Now find the smallest one larger than the requested size */
341 maxwidth = maxheight = 255;
342 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
343 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
344 (entry->wBitCount == 1))
347 maxwidth = entry->ResInfo.cursor.wWidth;
348 maxheight = entry->ResInfo.cursor.wHeight;
354 /*********************************************************************
355 * The main purpose of this function is to create fake resource directory
356 * and fake resource entries. There are several reasons for this:
357 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
359 * There are some "bad" cursor files which do not have
360 * bColorCount initialized but instead one must read this info
361 * directly from corresponding DIB sections
362 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
364 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
365 CURSORICONDIR **res, LPBYTE **ptr)
368 CURSORICONFILEDIR *bits;
369 int entries, size, i;
373 if (!(bits = map_fileW( filename ))) return FALSE;
375 /* FIXME: test for inimated icons
376 * hack to load the first icon from the *.ani file
378 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
379 { LPBYTE pos = (LPBYTE) bits;
380 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
383 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
384 { FIXME_(cursor)("icon entry found! %p\n", bits);
386 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
389 bits=(CURSORICONFILEDIR*)(pos+4);
390 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
394 if (pos>=(LPBYTE)bits+766) goto fail;
397 if (!(entries = bits->idCount)) goto fail;
398 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
399 _free = (LPBYTE) size;
401 for (i=0; i < entries; i++)
402 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
404 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
405 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
406 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
408 _free = (LPBYTE)(*res) + (int)_free;
409 memcpy((*res), bits, 6);
410 for (i=0; i<entries; i++)
412 ((LPBYTE*)(*ptr))[i] = _free;
414 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
415 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
416 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
417 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
418 _free+=sizeof(POINT16);
420 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
421 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
422 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
424 (*res)->idEntries[i].wPlanes=1;
425 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
426 bits->idEntries[i].dwDIBOffset))->biBitCount;
427 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
428 (*res)->idEntries[i].wResId=i+1;
430 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
431 (*res)->idEntries[i].dwBytesInRes);
432 _free += (*res)->idEntries[i].dwBytesInRes;
434 UnmapViewOfFile( bits );
437 if (*res) HeapFree( GetProcessHeap(), 0, *res );
438 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
439 UnmapViewOfFile( bits );
444 /**********************************************************************
445 * CURSORICON_CreateFromResource
447 * Create a cursor or icon from in-memory resource template.
449 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
450 * with cbSize parameter as well.
452 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
453 UINT cbSize, BOOL bIcon, DWORD dwVersion,
454 INT width, INT height, UINT loadflags )
456 int sizeAnd, sizeXor;
457 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
458 BITMAP bmpXor, bmpAnd;
465 hotspot.x = ICON_HOTSPOT;
466 hotspot.y = ICON_HOTSPOT;
468 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
469 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
470 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
471 if (dwVersion == 0x00020000)
473 FIXME_(cursor)("\t2.xx resources are not supported\n");
478 bmi = (BITMAPINFO *)bits;
479 else /* get the hotspot */
481 POINT16 *pt = (POINT16 *)bits;
483 bmi = (BITMAPINFO *)(pt + 1);
485 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
487 if (!width) width = bmi->bmiHeader.biWidth;
488 if (!height) height = bmi->bmiHeader.biHeight/2;
489 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
490 (bmi->bmiHeader.biWidth != width);
492 /* Check bitmap header */
494 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
495 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
496 bmi->bmiHeader.biCompression != BI_RGB) )
498 WARN_(cursor)("\tinvalid resource bitmap header.\n");
502 if( (hdc = GetDC( 0 )) )
506 /* Make sure we have room for the monochrome bitmap later on.
507 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
508 * up to and including the biBitCount. In-memory icon resource
509 * format is as follows:
511 * BITMAPINFOHEADER icHeader // DIB header
512 * RGBQUAD icColors[] // Color table
513 * BYTE icXOR[] // DIB bits for XOR mask
514 * BYTE icAND[] // DIB bits for AND mask
517 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
518 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
520 memcpy( pInfo, bmi, size );
521 pInfo->bmiHeader.biHeight /= 2;
523 /* Create the XOR bitmap */
528 hXorBits = CreateCompatibleBitmap(hdc, width, height);
532 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
537 HDC hMem = CreateCompatibleDC(hdc);
541 hOld = SelectObject(hMem, hXorBits);
542 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
543 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
544 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
545 SelectObject(hMem, hOld);
548 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
550 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
551 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
554 char* xbits = (char *)bmi + size +
555 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
556 bmi->bmiHeader.biHeight,
557 bmi->bmiHeader.biBitCount) / 2;
559 pInfo->bmiHeader.biBitCount = 1;
560 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
562 RGBQUAD *rgb = pInfo->bmiColors;
564 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
565 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
566 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
567 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
571 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
573 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
574 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
577 /* Create the AND bitmap */
580 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
582 HDC hMem = CreateCompatibleDC(hdc);
586 hOld = SelectObject(hMem, hAndBits);
587 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
588 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
589 xbits, pInfo, DIB_RGB_COLORS, SRCCOPY);
590 SelectObject(hMem, hOld);
593 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
595 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
596 CBM_INIT, xbits, pInfo, DIB_RGB_COLORS );
598 if( !hAndBits ) DeleteObject( hXorBits );
600 HeapFree( GetProcessHeap(), 0, pInfo );
605 if( !hXorBits || !hAndBits )
607 WARN_(cursor)("\tunable to create an icon bitmap.\n");
611 /* Now create the CURSORICONINFO structure */
612 GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor );
613 GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd );
614 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
615 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
617 if (hObj) hObj = GlobalReAlloc16( hObj,
618 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
619 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
620 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
623 CURSORICONINFO *info;
625 /* Make it owned by the module */
626 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
628 info = (CURSORICONINFO *)GlobalLock16( hObj );
629 info->ptHotSpot.x = hotspot.x;
630 info->ptHotSpot.y = hotspot.y;
631 info->nWidth = bmpXor.bmWidth;
632 info->nHeight = bmpXor.bmHeight;
633 info->nWidthBytes = bmpXor.bmWidthBytes;
634 info->bPlanes = bmpXor.bmPlanes;
635 info->bBitsPerPixel = bmpXor.bmBitsPixel;
637 /* Transfer the bitmap bits to the CURSORICONINFO structure */
639 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
640 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
641 GlobalUnlock16( hObj );
644 DeleteObject( hAndBits );
645 DeleteObject( hXorBits );
650 /**********************************************************************
651 * CreateIconFromResourceEx (USER.450)
653 * FIXME: not sure about exact parameter types
655 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
656 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
658 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
659 width, height, cFlag);
663 /**********************************************************************
664 * CreateIconFromResource (USER32.@)
666 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
667 BOOL bIcon, DWORD dwVersion)
669 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
673 /**********************************************************************
674 * CreateIconFromResourceEx (USER32.@)
676 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
677 BOOL bIcon, DWORD dwVersion,
678 INT width, INT height,
681 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
683 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
684 width, height, cFlag );
688 /**********************************************************************
691 * Load a cursor or icon from resource or file.
693 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
694 INT width, INT height, INT colors,
695 BOOL fCursor, UINT loadflags )
697 HANDLE handle = 0, h = 0;
700 CURSORICONDIRENTRY *dirEntry;
703 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
706 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
709 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
711 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
712 bits = ptr[dirEntry->wResId-1];
713 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
714 !fCursor, 0x00030000, width, height, loadflags);
715 HeapFree( GetProcessHeap(), 0, dir );
716 HeapFree( GetProcessHeap(), 0, ptr );
719 else if ( !hInstance ) /* Load OEM cursor/icon */
725 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
726 if( ansi[0]=='#') /*Check for '#xxx' name */
728 resid = atoi(ansi+1);
729 HeapFree( GetProcessHeap(), 0, ansi );
733 HeapFree( GetProcessHeap(), 0, ansi );
737 else resid = LOWORD(name);
738 h = USER_Driver.pLoadOEMResource( resid, fCursor ? OEM_CURSOR : OEM_ICON );
741 else /* Load from resource */
747 /* Normalize hInstance (must be uniquely represented for icon cache) */
749 if ( HIWORD( hInstance ) )
750 hInstance = MapHModuleLS( hInstance );
752 hInstance = GetExePtr( hInstance );
754 /* Get directory resource ID */
756 if (!(hRsrc = FindResourceW( hInstance, name,
757 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
761 /* Find the best entry in the directory */
763 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
764 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
766 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
769 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
770 width, height, colors );
771 if (!dirEntry) return 0;
772 wResId = dirEntry->wResId;
773 dwBytesInRes = dirEntry->dwBytesInRes;
774 FreeResource( handle );
776 /* Load the resource */
778 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
779 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
781 /* If shared icon, check whether it was already loaded */
782 if ( (loadflags & LR_SHARED)
783 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
786 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
787 bits = (LPBYTE)LockResource( handle );
788 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
789 !fCursor, 0x00030000, width, height, loadflags);
790 FreeResource( handle );
792 /* If shared icon, add to icon cache */
794 if ( h && (loadflags & LR_SHARED) )
795 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
801 /***********************************************************************
804 * Make a copy of a cursor or icon.
806 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
808 char *ptrOld, *ptrNew;
812 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
813 if (!(hInstance = GetExePtr( hInstance ))) return 0;
814 size = GlobalSize16( handle );
815 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
816 FarSetOwner16( hNew, hInstance );
817 ptrNew = (char *)GlobalLock16( hNew );
818 memcpy( ptrNew, ptrOld, size );
819 GlobalUnlock16( handle );
820 GlobalUnlock16( hNew );
824 /*************************************************************************
827 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
830 * Handle [I] handle to an Image
831 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
832 * iDesiredCX [I] The Desired width of the Image
833 * iDesiredCY [I] The desired height of the Image
834 * nFlags [I] The flags from CopyImage
837 * Success: The new handle of the Image
840 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
841 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
842 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
847 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
848 INT iDesiredCX, INT iDesiredCY,
853 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
854 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
861 /* Best Fit or Monochrome */
862 if( (nFlags & LR_COPYFROMRESOURCE
863 && (iDesiredCX > 0 || iDesiredCY > 0))
864 || nFlags & LR_MONOCHROME)
866 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
868 /* Not Found in Cache, then do a strait copy
870 if(pIconCache == NULL)
872 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
873 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
874 if(nFlags & LR_COPYFROMRESOURCE)
876 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
881 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
888 CURSORICONDIRENTRY *pDirEntry;
889 BOOL bIsIcon = (nType == IMAGE_ICON);
891 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
893 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
894 || (iDesiredCX == 0 && iDesiredCY == 0))
896 iDesiredCY = GetSystemMetrics(bIsIcon ?
897 SM_CYICON : SM_CYCURSOR);
898 iDesiredCX = GetSystemMetrics(bIsIcon ?
899 SM_CXICON : SM_CXCURSOR);
902 /* Retreive the CURSORICONDIRENTRY
904 if (!(hMem = LoadResource( pIconCache->hModule ,
905 pIconCache->hGroupRsrc)))
909 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
918 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
919 pDir, iDesiredCX, iDesiredCY, 256);
923 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
924 pDir, iDesiredCX, iDesiredCY, 1);
927 wResId = pDirEntry->wResId;
928 dwBytesInRes = pDirEntry->dwBytesInRes;
931 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
932 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
933 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
937 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
938 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
942 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
947 pBits = (LPBYTE)LockResource( hMem );
949 if(nFlags & LR_DEFAULTSIZE)
951 iTargetCY = GetSystemMetrics(SM_CYICON);
952 iTargetCX = GetSystemMetrics(SM_CXICON);
955 /* Create a New Icon with the proper dimension
957 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
958 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
964 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
965 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
970 /***********************************************************************
971 * CURSORICON_IconToCursor
973 * Converts bitmap to mono and truncates if icon is too large (should
974 * probably do StretchBlt() instead).
976 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
979 CURSORICONINFO *pIcon = NULL;
980 HTASK16 hTask = GetCurrentTask();
981 TDB* pTask = (TDB *)GlobalLock16(hTask);
984 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
985 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
987 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
990 pIcon = GlobalLock16(hRet);
992 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
994 GlobalUnlock16(hRet);
1000 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
1001 BYTE* psPtr, *pxbPtr = pXorBits;
1002 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
1007 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
1008 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
1010 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
1011 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
1012 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
1014 memset(pXorBits, 0, 128);
1015 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
1016 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
1017 cI.nWidth = 32; cI.nHeight = 32;
1018 cI.nWidthBytes = 4; /* 32x1bpp */
1020 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
1021 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
1023 for( iy = 0; iy < maxy; iy++ )
1025 unsigned shift = iy % 2;
1027 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
1028 (and_width > 4) ? 4 : and_width );
1029 for( ix = 0; ix < maxx; ix++ )
1031 if( bSemiTransparent && ((ix+shift)%2) )
1033 /* set AND bit, XOR bit stays 0 */
1035 pbc = pAndBits + iy * 4 + ix/8;
1036 *pbc |= 0x80 >> (ix%8);
1040 /* keep AND bit, set XOR bit */
1042 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1043 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1044 if(!PALETTE_Driver->pIsDark(val))
1046 pbc = pxbPtr + ix/8;
1047 *pbc |= 0x80 >> (ix%8);
1055 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
1057 if( !hRet ) /* fall back on default drag cursor */
1058 hRet = CURSORICON_Copy( pTask->hInstance ,
1059 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1060 GetSystemMetrics(SM_CXCURSOR),
1061 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1068 /***********************************************************************
1069 * LoadCursor (USER.173)
1071 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, LPCSTR name )
1073 return LoadCursorA( hInstance, name );
1077 /***********************************************************************
1078 * LoadIcon (USER.174)
1080 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, LPCSTR name )
1082 return LoadIconA( hInstance, name );
1086 /***********************************************************************
1087 * CreateCursor (USER.406)
1089 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1090 INT16 xHotSpot, INT16 yHotSpot,
1091 INT16 nWidth, INT16 nHeight,
1092 LPCVOID lpANDbits, LPCVOID lpXORbits )
1094 CURSORICONINFO info;
1096 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1097 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1099 info.ptHotSpot.x = xHotSpot;
1100 info.ptHotSpot.y = yHotSpot;
1101 info.nWidth = nWidth;
1102 info.nHeight = nHeight;
1103 info.nWidthBytes = 0;
1105 info.bBitsPerPixel = 1;
1107 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1111 /***********************************************************************
1112 * CreateCursor (USER32.@)
1114 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1115 INT xHotSpot, INT yHotSpot,
1116 INT nWidth, INT nHeight,
1117 LPCVOID lpANDbits, LPCVOID lpXORbits )
1119 CURSORICONINFO info;
1121 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1122 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1124 info.ptHotSpot.x = xHotSpot;
1125 info.ptHotSpot.y = yHotSpot;
1126 info.nWidth = nWidth;
1127 info.nHeight = nHeight;
1128 info.nWidthBytes = 0;
1130 info.bBitsPerPixel = 1;
1132 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1136 /***********************************************************************
1137 * CreateIcon (USER.407)
1139 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1140 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1141 LPCVOID lpANDbits, LPCVOID lpXORbits )
1143 CURSORICONINFO info;
1145 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1146 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1148 info.ptHotSpot.x = ICON_HOTSPOT;
1149 info.ptHotSpot.y = ICON_HOTSPOT;
1150 info.nWidth = nWidth;
1151 info.nHeight = nHeight;
1152 info.nWidthBytes = 0;
1153 info.bPlanes = bPlanes;
1154 info.bBitsPerPixel = bBitsPixel;
1156 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1160 /***********************************************************************
1161 * CreateIcon (USER32.@)
1163 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1164 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
1165 LPCVOID lpANDbits, LPCVOID lpXORbits )
1167 CURSORICONINFO info;
1169 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1170 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1172 info.ptHotSpot.x = ICON_HOTSPOT;
1173 info.ptHotSpot.y = ICON_HOTSPOT;
1174 info.nWidth = nWidth;
1175 info.nHeight = nHeight;
1176 info.nWidthBytes = 0;
1177 info.bPlanes = bPlanes;
1178 info.bBitsPerPixel = bBitsPixel;
1180 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1184 /***********************************************************************
1185 * CreateCursorIconIndirect (USER.408)
1187 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1188 CURSORICONINFO *info,
1194 int sizeAnd, sizeXor;
1196 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1197 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1198 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1199 sizeXor = info->nHeight * info->nWidthBytes;
1200 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1201 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1202 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1204 if (hInstance) FarSetOwner16( handle, hInstance );
1205 ptr = (char *)GlobalLock16( handle );
1206 memcpy( ptr, info, sizeof(*info) );
1207 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1208 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1209 GlobalUnlock16( handle );
1214 /***********************************************************************
1215 * CopyIcon (USER.368)
1217 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1219 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1220 return CURSORICON_Copy( hInstance, hIcon );
1224 /***********************************************************************
1225 * CopyIcon (USER32.@)
1227 HICON WINAPI CopyIcon( HICON hIcon )
1229 HTASK16 hTask = GetCurrentTask ();
1230 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1231 TRACE_(icon)("%04x\n", hIcon );
1232 return CURSORICON_Copy( pTask->hInstance, hIcon );
1236 /***********************************************************************
1237 * CopyCursor (USER.369)
1239 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1241 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1242 return CURSORICON_Copy( hInstance, hCursor );
1245 /**********************************************************************
1246 * DestroyIcon32 (USER.610)
1248 * This routine is actually exported from Win95 USER under the name
1249 * DestroyIcon32 ... The behaviour implemented here should mimic
1250 * the Win95 one exactly, especially the return values, which
1251 * depend on the setting of various flags.
1253 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1257 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1259 /* Check whether destroying active cursor */
1261 if ( hActiveCursor == handle )
1263 ERR_(cursor)("Destroying active cursor!\n" );
1267 /* Try shared cursor/icon first */
1269 if ( !(flags & CID_NONSHARED) )
1271 INT count = CURSORICON_DelSharedIcon( handle );
1274 return (flags & CID_WIN32)? TRUE : (count == 0);
1276 /* FIXME: OEM cursors/icons should be recognized */
1279 /* Now assume non-shared cursor/icon */
1281 retv = GlobalFree16( handle );
1282 return (flags & CID_RESOURCE)? retv : TRUE;
1285 /***********************************************************************
1286 * DestroyIcon16 (USER.457)
1288 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1290 return CURSORICON_Destroy( hIcon, 0 );
1293 /***********************************************************************
1294 * DestroyIcon (USER32.@)
1296 BOOL WINAPI DestroyIcon( HICON hIcon )
1298 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1301 /***********************************************************************
1302 * DestroyCursor (USER.458)
1304 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1306 return CURSORICON_Destroy( hCursor, 0 );
1309 /***********************************************************************
1310 * DestroyCursor (USER32.@)
1312 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1314 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1318 /***********************************************************************
1319 * DrawIcon (USER.84)
1321 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1323 return DrawIcon( hdc, x, y, hIcon );
1327 /***********************************************************************
1328 * DrawIcon (USER32.@)
1330 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1332 CURSORICONINFO *ptr;
1334 HBITMAP hXorBits, hAndBits;
1335 COLORREF oldFg, oldBg;
1337 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1338 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1339 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1341 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1342 ptr->bBitsPerPixel, (char *)(ptr + 1)
1343 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1344 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1345 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1347 if (hXorBits && hAndBits)
1349 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1350 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1351 SelectObject( hMemDC, hXorBits );
1352 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1353 SelectObject( hMemDC, hBitTemp );
1356 if (hXorBits) DeleteObject( hXorBits );
1357 if (hAndBits) DeleteObject( hAndBits );
1358 GlobalUnlock16( hIcon );
1359 SetTextColor( hdc, oldFg );
1360 SetBkColor( hdc, oldBg );
1365 /***********************************************************************
1366 * IconSize (USER.86)
1368 * See "Undocumented Windows". Used by W2.0 paint.exe.
1370 DWORD WINAPI IconSize16( void )
1372 return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON));
1376 /***********************************************************************
1377 * DumpIcon (USER.459)
1379 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1380 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1382 CURSORICONINFO *info = MapSL( pInfo );
1383 int sizeAnd, sizeXor;
1385 if (!info) return 0;
1386 sizeXor = info->nHeight * info->nWidthBytes;
1387 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1388 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1389 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1390 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1391 return MAKELONG( sizeXor, sizeXor );
1395 /***********************************************************************
1396 * SetCursor (USER.69)
1398 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1400 return (HCURSOR16)SetCursor( hCursor );
1404 /***********************************************************************
1405 * SetCursor (USER32.@)
1407 * A handle to the previous cursor shape.
1409 HCURSOR WINAPI SetCursor(
1410 HCURSOR hCursor /* [in] Handle of cursor to show */
1414 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1415 TRACE_(cursor)("%04x\n", hCursor );
1416 hOldCursor = hActiveCursor;
1417 hActiveCursor = hCursor;
1418 /* Change the cursor shape only if it is visible */
1419 if (CURSOR_ShowCount >= 0)
1421 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1422 GlobalUnlock16( hActiveCursor );
1428 /***********************************************************************
1429 * SetCursorPos (USER.70)
1431 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1433 SetCursorPos( x, y );
1437 /***********************************************************************
1438 * SetCursorPos (USER32.@)
1440 BOOL WINAPI SetCursorPos( INT x, INT y )
1442 USER_Driver.pMoveCursor( x, y );
1447 /***********************************************************************
1448 * ShowCursor (USER.71)
1450 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1452 return ShowCursor( bShow );
1456 /***********************************************************************
1457 * ShowCursor (USER32.@)
1459 INT WINAPI ShowCursor( BOOL bShow )
1461 TRACE_(cursor)("%d, count=%d\n",
1462 bShow, CURSOR_ShowCount );
1466 if (++CURSOR_ShowCount == 0) /* Show it */
1468 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1469 GlobalUnlock16( hActiveCursor );
1474 if (--CURSOR_ShowCount == -1) /* Hide it */
1475 USER_Driver.pSetCursor( NULL );
1477 return CURSOR_ShowCount;
1481 /***********************************************************************
1482 * GetCursor (USER.247)
1484 HCURSOR16 WINAPI GetCursor16(void)
1486 return hActiveCursor;
1490 /***********************************************************************
1491 * GetCursor (USER32.@)
1493 HCURSOR WINAPI GetCursor(void)
1495 return hActiveCursor;
1499 /***********************************************************************
1500 * ClipCursor (USER.16)
1502 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1504 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1505 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1510 /***********************************************************************
1511 * ClipCursor (USER32.@)
1513 BOOL WINAPI ClipCursor( const RECT *rect )
1515 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1516 else CopyRect( &CURSOR_ClipRect, rect );
1521 /***********************************************************************
1522 * GetClipCursor (USER.309)
1524 void WINAPI GetClipCursor16( RECT16 *rect )
1526 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1530 /***********************************************************************
1531 * GetClipCursor (USER32.@)
1533 BOOL WINAPI GetClipCursor( RECT *rect )
1537 CopyRect( rect, &CURSOR_ClipRect );
1543 /**********************************************************************
1544 * LookupIconIdFromDirectoryEx (USER.364)
1546 * FIXME: exact parameter sizes
1548 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1549 INT16 width, INT16 height, UINT16 cFlag )
1551 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1553 if( dir && !dir->idReserved && (dir->idType & 3) )
1555 CURSORICONDIRENTRY* entry;
1560 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1563 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1568 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1570 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1572 if( entry ) retVal = entry->wResId;
1574 else WARN_(cursor)("invalid resource directory\n");
1578 /**********************************************************************
1579 * LookupIconIdFromDirectoryEx (USER32.@)
1581 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1582 INT width, INT height, UINT cFlag )
1584 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1587 /**********************************************************************
1588 * LookupIconIdFromDirectory (USER.???)
1590 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1592 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1593 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1594 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1597 /**********************************************************************
1598 * LookupIconIdFromDirectory (USER32.@)
1600 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1602 return LookupIconIdFromDirectoryEx( dir, bIcon,
1603 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1604 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1607 /**********************************************************************
1608 * GetIconID (USER.455)
1610 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1612 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1614 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1615 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1620 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1621 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1623 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1624 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1626 WARN_(cursor)("invalid res type %ld\n", resType );
1631 /**********************************************************************
1632 * LoadCursorIconHandler (USER.336)
1634 * Supposed to load resources of Windows 2.x applications.
1636 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1638 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1639 hResource, hModule, hRsrc);
1640 return (HGLOBAL16)0;
1643 /**********************************************************************
1644 * LoadDIBIconHandler (USER.357)
1646 * RT_ICON resource loader, installed by USER_SignalProc when module
1649 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1651 /* If hResource is zero we must allocate a new memory block, if it's
1652 * non-zero but GlobalLock() returns NULL then it was discarded and
1653 * we have to recommit some memory, otherwise we just need to check
1654 * the block size. See LoadProc() in 16-bit SDK for more.
1657 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1660 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1661 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1662 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1663 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1668 /**********************************************************************
1669 * LoadDIBCursorHandler (USER.356)
1671 * RT_CURSOR resource loader. Same as above.
1673 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1675 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1678 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1679 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1680 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1681 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1686 /**********************************************************************
1687 * LoadIconHandler (USER.456)
1689 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1691 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1693 TRACE_(cursor)("hRes=%04x\n",hResource);
1695 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1696 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1699 /***********************************************************************
1700 * LoadCursorW (USER32.@)
1702 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1704 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1705 LR_SHARED | LR_DEFAULTSIZE );
1708 /***********************************************************************
1709 * LoadCursorA (USER32.@)
1711 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1713 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1714 LR_SHARED | LR_DEFAULTSIZE );
1717 /***********************************************************************
1718 * LoadCursorFromFileW (USER32.@)
1720 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1722 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1723 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1726 /***********************************************************************
1727 * LoadCursorFromFileA (USER32.@)
1729 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1731 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1732 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1735 /***********************************************************************
1736 * LoadIconW (USER32.@)
1738 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1740 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1741 LR_SHARED | LR_DEFAULTSIZE );
1744 /***********************************************************************
1745 * LoadIconA (USER32.@)
1747 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1749 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1750 LR_SHARED | LR_DEFAULTSIZE );
1753 /**********************************************************************
1754 * GetIconInfo (USER.395)
1756 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1759 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1761 iconinfo->fIcon = ii32.fIcon;
1762 iconinfo->xHotspot = ii32.xHotspot;
1763 iconinfo->yHotspot = ii32.yHotspot;
1764 iconinfo->hbmMask = ii32.hbmMask;
1765 iconinfo->hbmColor = ii32.hbmColor;
1769 /**********************************************************************
1770 * GetIconInfo (USER32.@)
1772 BOOL WINAPI GetIconInfo(HICON hIcon,PICONINFO iconinfo) {
1773 CURSORICONINFO *ciconinfo;
1775 ciconinfo = GlobalLock16(hIcon);
1779 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1780 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1782 iconinfo->fIcon = TRUE;
1783 iconinfo->xHotspot = ciconinfo->nWidth / 2;
1784 iconinfo->yHotspot = ciconinfo->nHeight / 2;
1788 iconinfo->fIcon = FALSE;
1789 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1790 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1793 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1794 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1795 (char *)(ciconinfo + 1)
1796 + ciconinfo->nHeight *
1797 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1798 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1799 1, 1, (char *)(ciconinfo + 1));
1801 GlobalUnlock16(hIcon);
1806 /**********************************************************************
1807 * CreateIconIndirect (USER32.@)
1809 HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
1811 BITMAP bmpXor,bmpAnd;
1813 int sizeXor,sizeAnd;
1815 GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
1816 GetObjectA( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
1818 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
1819 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
1821 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1822 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1825 CURSORICONINFO *info;
1827 info = (CURSORICONINFO *)GlobalLock16( hObj );
1829 /* If we are creating an icon, the hotspot is unused */
1830 if (iconinfo->fIcon)
1832 info->ptHotSpot.x = ICON_HOTSPOT;
1833 info->ptHotSpot.y = ICON_HOTSPOT;
1837 info->ptHotSpot.x = iconinfo->xHotspot;
1838 info->ptHotSpot.y = iconinfo->yHotspot;
1841 info->nWidth = bmpXor.bmWidth;
1842 info->nHeight = bmpXor.bmHeight;
1843 info->nWidthBytes = bmpXor.bmWidthBytes;
1844 info->bPlanes = bmpXor.bmPlanes;
1845 info->bBitsPerPixel = bmpXor.bmBitsPixel;
1847 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1849 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1850 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1851 GlobalUnlock16( hObj );
1857 /**********************************************************************
1858 * DrawIconEx (USER.394)
1860 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1861 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1862 HBRUSH16 hbr, UINT16 flags)
1864 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1869 /******************************************************************************
1870 * DrawIconEx (USER32.@) Draws an icon or cursor on device context
1873 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1876 * hdc [I] Handle to device context
1877 * x0 [I] X coordinate of upper left corner
1878 * y0 [I] Y coordinate of upper left corner
1879 * hIcon [I] Handle to icon to draw
1880 * cxWidth [I] Width of icon
1881 * cyWidth [I] Height of icon
1882 * istep [I] Index of frame in animated cursor
1883 * hbr [I] Handle to background brush
1884 * flags [I] Icon-drawing flags
1890 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1891 INT cxWidth, INT cyWidth, UINT istep,
1892 HBRUSH hbr, UINT flags )
1894 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1895 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1896 BOOL result = FALSE, DoOffscreen;
1897 HBITMAP hB_off = 0, hOld = 0;
1899 if (!ptr) return FALSE;
1900 TRACE_(icon)("(hdc=%x,pos=%d.%d,hicon=%x,extend=%d.%d,istep=%d,br=%x,flags=0x%08x)\n",
1901 hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags
1905 FIXME_(icon)("Ignoring istep=%d\n", istep);
1906 if (flags & DI_COMPAT)
1907 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1910 FIXME_(icon)("no flags set? setting to DI_NORMAL\n");
1914 /* Calculate the size of the destination image. */
1917 if (flags & DI_DEFAULTSIZE)
1918 cxWidth = GetSystemMetrics (SM_CXICON);
1920 cxWidth = ptr->nWidth;
1924 if (flags & DI_DEFAULTSIZE)
1925 cyWidth = GetSystemMetrics (SM_CYICON);
1927 cyWidth = ptr->nHeight;
1930 DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
1940 hDC_off = CreateCompatibleDC(hdc);
1941 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1942 if (hDC_off && hB_off) {
1943 hOld = SelectObject(hDC_off, hB_off);
1944 FillRect(hDC_off, &r, hbr);
1948 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1950 HBITMAP hXorBits, hAndBits;
1951 COLORREF oldFg, oldBg;
1954 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1956 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1957 ptr->bPlanes, ptr->bBitsPerPixel,
1960 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1961 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1962 1, 1, (char *)(ptr+1) );
1963 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1964 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1966 if (hXorBits && hAndBits)
1968 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1969 if (flags & DI_MASK)
1972 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1973 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1975 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1976 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1978 SelectObject( hMemDC, hXorBits );
1979 if (flags & DI_IMAGE)
1982 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1983 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1985 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1986 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1988 SelectObject( hMemDC, hBitTemp );
1992 SetTextColor( hdc, oldFg );
1993 SetBkColor( hdc, oldBg );
1994 if (hXorBits) DeleteObject( hXorBits );
1995 if (hAndBits) DeleteObject( hAndBits );
1996 SetStretchBltMode (hdc, nStretchMode);
1998 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1999 SelectObject(hDC_off, hOld);
2002 if (hMemDC) DeleteDC( hMemDC );
2003 if (hDC_off) DeleteDC(hDC_off);
2004 if (hB_off) DeleteObject(hB_off);
2005 GlobalUnlock16( hIcon );
2009 /***********************************************************************
2010 * DIB_FixColorsToLoadflags
2012 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
2015 static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
2018 COLORREF c_W, c_S, c_F, c_L, c_C;
2022 if (bmi->bmiHeader.biBitCount > 8) return;
2023 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
2024 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
2026 WARN_(resource)("Wrong bitmap header size!\n");
2029 colors = bmi->bmiHeader.biClrUsed;
2030 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
2031 colors = 1 << bmi->bmiHeader.biBitCount;
2032 c_W = GetSysColor(COLOR_WINDOW);
2033 c_S = GetSysColor(COLOR_3DSHADOW);
2034 c_F = GetSysColor(COLOR_3DFACE);
2035 c_L = GetSysColor(COLOR_3DLIGHT);
2036 if (loadflags & LR_LOADTRANSPARENT) {
2037 switch (bmi->bmiHeader.biBitCount) {
2038 case 1: pix = pix >> 7; break;
2039 case 4: pix = pix >> 4; break;
2042 WARN_(resource)("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
2045 if (pix >= colors) {
2046 WARN_(resource)("pixel has color index greater than biClrUsed!\n");
2049 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
2050 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
2051 ptr->rgbBlue = GetBValue(c_W);
2052 ptr->rgbGreen = GetGValue(c_W);
2053 ptr->rgbRed = GetRValue(c_W);
2055 if (loadflags & LR_LOADMAP3DCOLORS)
2056 for (i=0; i<colors; i++) {
2057 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2058 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2059 if (c_C == RGB(128, 128, 128)) {
2060 ptr->rgbRed = GetRValue(c_S);
2061 ptr->rgbGreen = GetGValue(c_S);
2062 ptr->rgbBlue = GetBValue(c_S);
2063 } else if (c_C == RGB(192, 192, 192)) {
2064 ptr->rgbRed = GetRValue(c_F);
2065 ptr->rgbGreen = GetGValue(c_F);
2066 ptr->rgbBlue = GetBValue(c_F);
2067 } else if (c_C == RGB(223, 223, 223)) {
2068 ptr->rgbRed = GetRValue(c_L);
2069 ptr->rgbGreen = GetGValue(c_L);
2070 ptr->rgbBlue = GetBValue(c_L);
2076 /**********************************************************************
2079 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2081 HBITMAP hbitmap = 0;
2086 BITMAPINFO *info, *fix_info=NULL;
2090 if (!(loadflags & LR_LOADFROMFILE)) {
2091 if (!instance) /* OEM bitmap */
2093 if (HIWORD((int)name)) return 0;
2094 return USER_Driver.pLoadOEMResource( LOWORD((int)name), OEM_BITMAP );
2097 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2098 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2100 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2104 if (!(ptr = map_fileW( name ))) return 0;
2105 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2107 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2108 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2112 memcpy(fix_info, info, size);
2113 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2114 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2115 if ((hdc = GetDC(0)) != 0) {
2116 char *bits = (char *)info + size;
2117 if (loadflags & LR_CREATEDIBSECTION) {
2119 hbitmap = CreateDIBSection(hdc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2120 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2121 SetDIBits(hdc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2125 hbitmap = CreateDIBitmap( hdc, &fix_info->bmiHeader, CBM_INIT,
2126 bits, fix_info, DIB_RGB_COLORS );
2128 ReleaseDC( 0, hdc );
2133 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2138 /***********************************************************************
2139 * LoadImage16 (USER.389)
2142 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2143 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2145 return LoadImageA( hinst, name, type, desiredx, desiredy, loadflags );
2148 /**********************************************************************
2149 * LoadImageA (USER32.@)
2151 * FIXME: implementation lacks some features, see LR_ defines in windows.h
2154 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2155 INT desiredx, INT desiredy, UINT loadflags)
2160 if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
2161 else u_name=(LPWSTR)name;
2162 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2163 if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
2168 /******************************************************************************
2169 * LoadImageW (USER32.@) Loads an icon, cursor, or bitmap
2172 * hinst [I] Handle of instance that contains image
2173 * name [I] Name of image
2174 * type [I] Type of image
2175 * desiredx [I] Desired width
2176 * desiredy [I] Desired height
2177 * loadflags [I] Load flags
2180 * Success: Handle to newly loaded image
2183 * FIXME: Implementation lacks some features, see LR_ defines in windows.h
2185 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2186 INT desiredx, INT desiredy, UINT loadflags )
2189 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2190 hinst,name,type,desiredx,desiredy,loadflags);
2192 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2193 hinst,name,type,desiredx,desiredy,loadflags);
2195 if (loadflags & LR_DEFAULTSIZE) {
2196 if (type == IMAGE_ICON) {
2197 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2198 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2199 } else if (type == IMAGE_CURSOR) {
2200 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2201 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2204 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2207 return BITMAP_Load( hinst, name, loadflags );
2212 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
2217 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2218 palEnts, FALSE, loadflags);
2222 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2223 1, TRUE, loadflags);
2229 /******************************************************************************
2230 * CopyImage (USER.390) Creates new image and copies attributes to it
2233 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2234 INT16 desiredy, UINT16 flags )
2236 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2237 (INT)desiredy, (UINT)flags);
2240 /******************************************************************************
2241 * CopyImage (USER32.@) Creates new image and copies attributes to it
2244 * hnd [I] Handle to image to copy
2245 * type [I] Type of image to copy
2246 * desiredx [I] Desired width of new image
2247 * desiredy [I] Desired height of new image
2248 * flags [I] Copy flags
2251 * Success: Handle to newly created image
2254 * FIXME: implementation still lacks nearly all features, see LR_*
2255 * defines in windows.h
2257 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2258 INT desiredy, UINT flags )
2263 return BITMAP_CopyBitmap(hnd);
2265 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2267 /* Should call CURSORICON_ExtCopy but more testing
2268 * needs to be done before we change this
2270 return CopyCursor(hnd);
2276 /******************************************************************************
2277 * LoadBitmapW (USER32.@) Loads bitmap from the executable file
2280 * Success: Handle to specified bitmap
2283 HBITMAP WINAPI LoadBitmapW(
2284 HINSTANCE instance, /* [in] Handle to application instance */
2285 LPCWSTR name) /* [in] Address of bitmap resource name */
2287 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2290 /**********************************************************************
2291 * LoadBitmapA (USER32.@)
2293 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2295 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2298 /**********************************************************************
2299 * LoadBitmap (USER.175)
2301 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, LPCSTR name )
2303 return LoadBitmapA( instance, name );