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 * CreateIconFromResourceEx16 (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.76)
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.77)
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 * LoadCursor16 (USER.173)
1071 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, LPCSTR name )
1073 return LoadCursorA( hInstance, name );
1077 /***********************************************************************
1078 * LoadIcon16 (USER.174)
1080 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, LPCSTR name )
1082 return LoadIconA( hInstance, name );
1086 /***********************************************************************
1087 * CreateCursor16 (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.67)
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 * CreateIcon16 (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.75)
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 * CopyIcon16 (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.60)
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 * CopyCursor16 (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 * CURSORICON_Destroy (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.133)
1296 BOOL WINAPI DestroyIcon( HICON hIcon )
1298 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1301 /***********************************************************************
1302 * DestroyCursor16 (USER.458)
1304 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1306 return CURSORICON_Destroy( hCursor, 0 );
1309 /***********************************************************************
1310 * DestroyCursor (USER32.132)
1312 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1314 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1318 /***********************************************************************
1319 * DrawIcon16 (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.159)
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 * IconSize16 (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 * SetCursor16 (USER.69)
1398 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1400 return (HCURSOR16)SetCursor( hCursor );
1404 /***********************************************************************
1405 * SetCursor (USER32.472)
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 * SetCursorPos16 (USER.70)
1431 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1433 SetCursorPos( x, y );
1437 /***********************************************************************
1438 * SetCursorPos (USER32.474)
1440 BOOL WINAPI SetCursorPos( INT x, INT y )
1442 USER_Driver.pMoveCursor( x, y );
1447 /***********************************************************************
1448 * ShowCursor16 (USER.71)
1450 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1452 return ShowCursor( bShow );
1456 /***********************************************************************
1457 * ShowCursor (USER32.530)
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 * GetCursor16 (USER.247)
1484 HCURSOR16 WINAPI GetCursor16(void)
1486 return hActiveCursor;
1490 /***********************************************************************
1491 * GetCursor (USER32.227)
1493 HCURSOR WINAPI GetCursor(void)
1495 return hActiveCursor;
1499 /***********************************************************************
1500 * ClipCursor16 (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.53)
1513 BOOL WINAPI ClipCursor( const RECT *rect )
1515 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1516 else CopyRect( &CURSOR_ClipRect, rect );
1521 /***********************************************************************
1522 * GetClipCursor16 (USER.309)
1524 void WINAPI GetClipCursor16( RECT16 *rect )
1526 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1530 /***********************************************************************
1531 * GetClipCursor (USER32.221)
1533 BOOL WINAPI GetClipCursor( RECT *rect )
1537 CopyRect( rect, &CURSOR_ClipRect );
1543 /**********************************************************************
1544 * LookupIconIdFromDirectoryEx16 (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.380)
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.379)
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.362)
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.359)
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.361)
1720 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1722 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1723 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1726 /***********************************************************************
1727 * LoadCursorFromFileA (USER32.360)
1729 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1731 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1732 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1735 /***********************************************************************
1736 * LoadIconW (USER32.364)
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.363)
1747 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1749 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1750 LR_SHARED | LR_DEFAULTSIZE );
1753 /**********************************************************************
1754 * GetIconInfo16 (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.242)
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.78)
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 /**********************************************************************
1859 DrawIconEx16 (USER.394)
1861 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1862 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1863 HBRUSH16 hbr, UINT16 flags)
1865 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1870 /******************************************************************************
1871 * DrawIconEx [USER32.160] Draws an icon or cursor on device context
1874 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1877 * hdc [I] Handle to device context
1878 * x0 [I] X coordinate of upper left corner
1879 * y0 [I] Y coordinate of upper left corner
1880 * hIcon [I] Handle to icon to draw
1881 * cxWidth [I] Width of icon
1882 * cyWidth [I] Height of icon
1883 * istep [I] Index of frame in animated cursor
1884 * hbr [I] Handle to background brush
1885 * flags [I] Icon-drawing flags
1891 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1892 INT cxWidth, INT cyWidth, UINT istep,
1893 HBRUSH hbr, UINT flags )
1895 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1896 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1897 BOOL result = FALSE, DoOffscreen;
1898 HBITMAP hB_off = 0, hOld = 0;
1900 if (!ptr) return FALSE;
1901 TRACE_(icon)("(hdc=%x,pos=%d.%d,hicon=%x,extend=%d.%d,istep=%d,br=%x,flags=0x%08x)\n",
1902 hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags
1906 FIXME_(icon)("Ignoring istep=%d\n", istep);
1907 if (flags & DI_COMPAT)
1908 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1911 FIXME_(icon)("no flags set? setting to DI_NORMAL\n");
1915 /* Calculate the size of the destination image. */
1918 if (flags & DI_DEFAULTSIZE)
1919 cxWidth = GetSystemMetrics (SM_CXICON);
1921 cxWidth = ptr->nWidth;
1925 if (flags & DI_DEFAULTSIZE)
1926 cyWidth = GetSystemMetrics (SM_CYICON);
1928 cyWidth = ptr->nHeight;
1931 DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
1941 hDC_off = CreateCompatibleDC(hdc);
1942 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1943 if (hDC_off && hB_off) {
1944 hOld = SelectObject(hDC_off, hB_off);
1945 FillRect(hDC_off, &r, hbr);
1949 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1951 HBITMAP hXorBits, hAndBits;
1952 COLORREF oldFg, oldBg;
1955 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1957 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1958 ptr->bPlanes, ptr->bBitsPerPixel,
1961 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1962 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1963 1, 1, (char *)(ptr+1) );
1964 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1965 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1967 if (hXorBits && hAndBits)
1969 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1970 if (flags & DI_MASK)
1973 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1974 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1976 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1977 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1979 SelectObject( hMemDC, hXorBits );
1980 if (flags & DI_IMAGE)
1983 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1984 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1986 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1987 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1989 SelectObject( hMemDC, hBitTemp );
1993 SetTextColor( hdc, oldFg );
1994 SetBkColor( hdc, oldBg );
1995 if (hXorBits) DeleteObject( hXorBits );
1996 if (hAndBits) DeleteObject( hAndBits );
1997 SetStretchBltMode (hdc, nStretchMode);
1999 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2000 SelectObject(hDC_off, hOld);
2003 if (hMemDC) DeleteDC( hMemDC );
2004 if (hDC_off) DeleteDC(hDC_off);
2005 if (hB_off) DeleteObject(hB_off);
2006 GlobalUnlock16( hIcon );
2010 /***********************************************************************
2011 * DIB_FixColorsToLoadflags
2013 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
2016 static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
2019 COLORREF c_W, c_S, c_F, c_L, c_C;
2023 if (bmi->bmiHeader.biBitCount > 8) return;
2024 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
2025 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
2027 WARN_(resource)("Wrong bitmap header size!\n");
2030 colors = bmi->bmiHeader.biClrUsed;
2031 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
2032 colors = 1 << bmi->bmiHeader.biBitCount;
2033 c_W = GetSysColor(COLOR_WINDOW);
2034 c_S = GetSysColor(COLOR_3DSHADOW);
2035 c_F = GetSysColor(COLOR_3DFACE);
2036 c_L = GetSysColor(COLOR_3DLIGHT);
2037 if (loadflags & LR_LOADTRANSPARENT) {
2038 switch (bmi->bmiHeader.biBitCount) {
2039 case 1: pix = pix >> 7; break;
2040 case 4: pix = pix >> 4; break;
2043 WARN_(resource)("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
2046 if (pix >= colors) {
2047 WARN_(resource)("pixel has color index greater than biClrUsed!\n");
2050 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
2051 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
2052 ptr->rgbBlue = GetBValue(c_W);
2053 ptr->rgbGreen = GetGValue(c_W);
2054 ptr->rgbRed = GetRValue(c_W);
2056 if (loadflags & LR_LOADMAP3DCOLORS)
2057 for (i=0; i<colors; i++) {
2058 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2059 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2060 if (c_C == RGB(128, 128, 128)) {
2061 ptr->rgbRed = GetRValue(c_S);
2062 ptr->rgbGreen = GetGValue(c_S);
2063 ptr->rgbBlue = GetBValue(c_S);
2064 } else if (c_C == RGB(192, 192, 192)) {
2065 ptr->rgbRed = GetRValue(c_F);
2066 ptr->rgbGreen = GetGValue(c_F);
2067 ptr->rgbBlue = GetBValue(c_F);
2068 } else if (c_C == RGB(223, 223, 223)) {
2069 ptr->rgbRed = GetRValue(c_L);
2070 ptr->rgbGreen = GetGValue(c_L);
2071 ptr->rgbBlue = GetBValue(c_L);
2077 /**********************************************************************
2080 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2082 HBITMAP hbitmap = 0;
2087 BITMAPINFO *info, *fix_info=NULL;
2091 if (!(loadflags & LR_LOADFROMFILE)) {
2092 if (!instance) /* OEM bitmap */
2094 if (HIWORD((int)name)) return 0;
2095 return USER_Driver.pLoadOEMResource( LOWORD((int)name), OEM_BITMAP );
2098 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2099 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2101 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2105 if (!(ptr = map_fileW( name ))) return 0;
2106 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2108 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2109 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2113 memcpy(fix_info, info, size);
2114 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2115 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2116 if ((hdc = GetDC(0)) != 0) {
2117 char *bits = (char *)info + size;
2118 if (loadflags & LR_CREATEDIBSECTION) {
2120 hbitmap = CreateDIBSection(hdc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2121 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2122 SetDIBits(hdc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2126 hbitmap = CreateDIBitmap( hdc, &fix_info->bmiHeader, CBM_INIT,
2127 bits, fix_info, DIB_RGB_COLORS );
2129 ReleaseDC( 0, hdc );
2134 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2139 /***********************************************************************
2140 * LoadImage16 [USER.389]
2143 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2144 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2146 return LoadImageA( hinst, name, type, desiredx, desiredy, loadflags );
2149 /**********************************************************************
2150 * LoadImageA (USER32.365)
2152 * FIXME: implementation lacks some features, see LR_ defines in windows.h
2155 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2156 INT desiredx, INT desiredy, UINT loadflags)
2161 if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
2162 else u_name=(LPWSTR)name;
2163 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2164 if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
2169 /******************************************************************************
2170 * LoadImageW [USER32.366] Loads an icon, cursor, or bitmap
2173 * hinst [I] Handle of instance that contains image
2174 * name [I] Name of image
2175 * type [I] Type of image
2176 * desiredx [I] Desired width
2177 * desiredy [I] Desired height
2178 * loadflags [I] Load flags
2181 * Success: Handle to newly loaded image
2184 * FIXME: Implementation lacks some features, see LR_ defines in windows.h
2186 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2187 INT desiredx, INT desiredy, UINT loadflags )
2190 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2191 hinst,name,type,desiredx,desiredy,loadflags);
2193 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2194 hinst,name,type,desiredx,desiredy,loadflags);
2196 if (loadflags & LR_DEFAULTSIZE) {
2197 if (type == IMAGE_ICON) {
2198 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2199 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2200 } else if (type == IMAGE_CURSOR) {
2201 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2202 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2205 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2208 return BITMAP_Load( hinst, name, loadflags );
2213 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
2218 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2219 palEnts, FALSE, loadflags);
2223 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2224 1, TRUE, loadflags);
2230 /******************************************************************************
2231 * CopyImage16 [USER.390] Creates new image and copies attributes to it
2234 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2235 INT16 desiredy, UINT16 flags )
2237 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2238 (INT)desiredy, (UINT)flags);
2241 /******************************************************************************
2242 * CopyImage [USER32.61] Creates new image and copies attributes to it
2245 * hnd [I] Handle to image to copy
2246 * type [I] Type of image to copy
2247 * desiredx [I] Desired width of new image
2248 * desiredy [I] Desired height of new image
2249 * flags [I] Copy flags
2252 * Success: Handle to newly created image
2255 * FIXME: implementation still lacks nearly all features, see LR_*
2256 * defines in windows.h
2258 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2259 INT desiredy, UINT flags )
2264 return BITMAP_CopyBitmap(hnd);
2266 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2268 /* Should call CURSORICON_ExtCopy but more testing
2269 * needs to be done before we change this
2271 return CopyCursor(hnd);
2277 /******************************************************************************
2278 * LoadBitmapW [USER32.358] Loads bitmap from the executable file
2281 * Success: Handle to specified bitmap
2284 HBITMAP WINAPI LoadBitmapW(
2285 HINSTANCE instance, /* [in] Handle to application instance */
2286 LPCWSTR name) /* [in] Address of bitmap resource name */
2288 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2291 /**********************************************************************
2292 * LoadBitmapA (USER32.357)
2294 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2296 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2299 /**********************************************************************
2300 * LoadBitmap16 (USER.175)
2302 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, LPCSTR name )
2304 return LoadBitmapA( instance, name );