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"
50 DECLARE_DEBUG_CHANNEL(cursor);
51 DECLARE_DEBUG_CHANNEL(icon);
52 DECLARE_DEBUG_CHANNEL(resource);
54 static HCURSOR hActiveCursor = 0; /* Active cursor */
55 static INT CURSOR_ShowCount = 0; /* Cursor display count */
56 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 for each 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( GetProcessHeap(), 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( GetProcessHeap(), 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 )
457 int sizeAnd, sizeXor;
458 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
459 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 (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
507 /* Make sure we have room for the monochrome bitmap later on.
508 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
509 * up to and including the biBitCount. In-memory icon resource
510 * format is as follows:
512 * BITMAPINFOHEADER icHeader // DIB header
513 * RGBQUAD icColors[] // Color table
514 * BYTE icXOR[] // DIB bits for XOR mask
515 * BYTE icAND[] // DIB bits for AND mask
518 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
519 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
521 memcpy( pInfo, bmi, size );
522 pInfo->bmiHeader.biHeight /= 2;
524 /* Create the XOR bitmap */
529 hXorBits = CreateCompatibleBitmap(screen_dc, width, height);
533 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
540 if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc);
542 hOld = SelectObject(hdcMem, hXorBits);
543 res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0,
544 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
545 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
546 SelectObject(hdcMem, hOld);
548 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
550 } else hXorBits = CreateDIBitmap( screen_dc, &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))) {
584 if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc);
586 hOld = SelectObject(hdcMem, hAndBits);
587 res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0,
588 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
589 xbits, pInfo, DIB_RGB_COLORS, SRCCOPY);
590 SelectObject(hdcMem, hOld);
592 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
594 } else hAndBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
595 CBM_INIT, xbits, pInfo, DIB_RGB_COLORS );
597 if( !hAndBits ) DeleteObject( hXorBits );
599 HeapFree( GetProcessHeap(), 0, pInfo );
603 if( !hXorBits || !hAndBits )
605 WARN_(cursor)("\tunable to create an icon bitmap.\n");
609 /* Now create the CURSORICONINFO structure */
610 GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor );
611 GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd );
612 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
613 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
615 if (hObj) hObj = GlobalReAlloc16( hObj,
616 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
617 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
618 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
621 CURSORICONINFO *info;
623 /* Make it owned by the module */
624 if (hInstance) hInstance = GetExePtr(hInstance);
625 FarSetOwner16( hObj, hInstance );
627 info = (CURSORICONINFO *)GlobalLock16( hObj );
628 info->ptHotSpot.x = hotspot.x;
629 info->ptHotSpot.y = hotspot.y;
630 info->nWidth = bmpXor.bmWidth;
631 info->nHeight = bmpXor.bmHeight;
632 info->nWidthBytes = bmpXor.bmWidthBytes;
633 info->bPlanes = bmpXor.bmPlanes;
634 info->bBitsPerPixel = bmpXor.bmBitsPixel;
636 /* Transfer the bitmap bits to the CURSORICONINFO structure */
638 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
639 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
640 GlobalUnlock16( hObj );
643 DeleteObject( hAndBits );
644 DeleteObject( hXorBits );
649 /**********************************************************************
650 * CreateIconFromResourceEx (USER.450)
652 * FIXME: not sure about exact parameter types
654 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
655 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
657 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
658 width, height, cFlag);
662 /**********************************************************************
663 * CreateIconFromResource (USER32.@)
665 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
666 BOOL bIcon, DWORD dwVersion)
668 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
672 /**********************************************************************
673 * CreateIconFromResourceEx (USER32.@)
675 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
676 BOOL bIcon, DWORD dwVersion,
677 INT width, INT height,
680 return CURSORICON_CreateFromResource( 0, 0, bits, cbSize, bIcon, dwVersion,
681 width, height, cFlag );
684 /**********************************************************************
687 * Load a cursor or icon from resource or file.
689 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
690 INT width, INT height, INT colors,
691 BOOL fCursor, UINT loadflags )
693 HANDLE handle = 0, h = 0;
696 CURSORICONDIRENTRY *dirEntry;
699 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
702 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
705 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
707 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
708 bits = ptr[dirEntry->wResId-1];
709 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
710 !fCursor, 0x00030000, width, height, loadflags);
711 HeapFree( GetProcessHeap(), 0, dir );
712 HeapFree( GetProcessHeap(), 0, ptr );
714 else /* Load from resource */
720 if (!hInstance) /* Load OEM cursor/icon */
722 if (!(hInstance = GetModuleHandleA( "user32.dll" ))) return 0;
725 /* Normalize hInstance (must be uniquely represented for icon cache) */
727 if ( HIWORD( hInstance ) )
728 hInstance = MapHModuleLS( hInstance );
730 hInstance = GetExePtr( hInstance );
732 /* Get directory resource ID */
734 if (!(hRsrc = FindResourceW( hInstance, name,
735 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
739 /* Find the best entry in the directory */
741 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
742 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
744 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
747 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
748 width, height, colors );
749 if (!dirEntry) return 0;
750 wResId = dirEntry->wResId;
751 dwBytesInRes = dirEntry->dwBytesInRes;
752 FreeResource( handle );
754 /* Load the resource */
756 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
757 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
759 /* If shared icon, check whether it was already loaded */
760 if ( (loadflags & LR_SHARED)
761 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
764 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
765 bits = (LPBYTE)LockResource( handle );
766 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
767 !fCursor, 0x00030000, width, height, loadflags);
768 FreeResource( handle );
770 /* If shared icon, add to icon cache */
772 if ( h && (loadflags & LR_SHARED) )
773 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
779 /***********************************************************************
782 * Make a copy of a cursor or icon.
784 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
786 char *ptrOld, *ptrNew;
790 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
791 if (hInstance && !(hInstance = GetExePtr( hInstance ))) return 0;
792 size = GlobalSize16( handle );
793 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
794 FarSetOwner16( hNew, hInstance );
795 ptrNew = (char *)GlobalLock16( hNew );
796 memcpy( ptrNew, ptrOld, size );
797 GlobalUnlock16( handle );
798 GlobalUnlock16( hNew );
802 /*************************************************************************
805 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
808 * Handle [I] handle to an Image
809 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
810 * iDesiredCX [I] The Desired width of the Image
811 * iDesiredCY [I] The desired height of the Image
812 * nFlags [I] The flags from CopyImage
815 * Success: The new handle of the Image
818 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
819 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
820 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
825 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
826 INT iDesiredCX, INT iDesiredCY,
831 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
832 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
839 /* Best Fit or Monochrome */
840 if( (nFlags & LR_COPYFROMRESOURCE
841 && (iDesiredCX > 0 || iDesiredCY > 0))
842 || nFlags & LR_MONOCHROME)
844 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
846 /* Not Found in Cache, then do a straight copy
848 if(pIconCache == NULL)
850 hNew = CURSORICON_Copy(0, Handle);
851 if(nFlags & LR_COPYFROMRESOURCE)
853 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
858 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
865 CURSORICONDIRENTRY *pDirEntry;
866 BOOL bIsIcon = (nType == IMAGE_ICON);
868 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
870 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
871 || (iDesiredCX == 0 && iDesiredCY == 0))
873 iDesiredCY = GetSystemMetrics(bIsIcon ?
874 SM_CYICON : SM_CYCURSOR);
875 iDesiredCX = GetSystemMetrics(bIsIcon ?
876 SM_CXICON : SM_CXCURSOR);
879 /* Retrieve the CURSORICONDIRENTRY
881 if (!(hMem = LoadResource( pIconCache->hModule ,
882 pIconCache->hGroupRsrc)))
886 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
895 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
896 pDir, iDesiredCX, iDesiredCY, 256);
900 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
901 pDir, iDesiredCX, iDesiredCY, 1);
904 wResId = pDirEntry->wResId;
905 dwBytesInRes = pDirEntry->dwBytesInRes;
908 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
909 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
910 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
914 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
915 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
919 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
924 pBits = (LPBYTE)LockResource( hMem );
926 if(nFlags & LR_DEFAULTSIZE)
928 iTargetCY = GetSystemMetrics(SM_CYICON);
929 iTargetCX = GetSystemMetrics(SM_CXICON);
932 /* Create a New Icon with the proper dimension
934 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
935 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
939 else hNew = CURSORICON_Copy(0, Handle);
943 /***********************************************************************
944 * CURSORICON_IconToCursor
946 * Converts bitmap to mono and truncates if icon is too large (should
947 * probably do StretchBlt() instead).
949 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
952 CURSORICONINFO *pIcon = NULL;
955 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
956 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
958 hRet = CURSORICON_Copy( 0, hIcon );
961 pIcon = GlobalLock16(hRet);
963 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
965 GlobalUnlock16(hRet);
971 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
972 BYTE* psPtr, *pxbPtr = pXorBits;
973 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
978 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
979 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
981 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
982 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
983 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
985 memset(pXorBits, 0, 128);
986 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
987 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
988 cI.nWidth = 32; cI.nHeight = 32;
989 cI.nWidthBytes = 4; /* 32x1bpp */
991 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
992 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
994 for( iy = 0; iy < maxy; iy++ )
996 unsigned shift = iy % 2;
998 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
999 (and_width > 4) ? 4 : and_width );
1000 for( ix = 0; ix < maxx; ix++ )
1002 if( bSemiTransparent && ((ix+shift)%2) )
1004 /* set AND bit, XOR bit stays 0 */
1006 pbc = pAndBits + iy * 4 + ix/8;
1007 *pbc |= 0x80 >> (ix%8);
1011 /* keep AND bit, set XOR bit */
1013 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1014 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1015 if(!PALETTE_Driver->pIsDark(val))
1017 pbc = pxbPtr + ix/8;
1018 *pbc |= 0x80 >> (ix%8);
1026 hRet = CreateCursorIconIndirect16( 0 , &cI, pAndBits, pXorBits);
1028 if( !hRet ) /* fall back on default drag cursor */
1029 hRet = CURSORICON_Copy( 0 ,
1030 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1031 GetSystemMetrics(SM_CXCURSOR),
1032 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1039 /***********************************************************************
1040 * LoadCursor (USER.173)
1042 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, LPCSTR name )
1044 return LoadCursorA( hInstance, name );
1048 /***********************************************************************
1049 * LoadIcon (USER.174)
1051 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, LPCSTR name )
1053 return LoadIconA( hInstance, name );
1057 /***********************************************************************
1058 * CreateCursor (USER.406)
1060 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1061 INT16 xHotSpot, INT16 yHotSpot,
1062 INT16 nWidth, INT16 nHeight,
1063 LPCVOID lpANDbits, LPCVOID lpXORbits )
1065 CURSORICONINFO info;
1067 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1068 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1070 info.ptHotSpot.x = xHotSpot;
1071 info.ptHotSpot.y = yHotSpot;
1072 info.nWidth = nWidth;
1073 info.nHeight = nHeight;
1074 info.nWidthBytes = 0;
1076 info.bBitsPerPixel = 1;
1078 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1082 /***********************************************************************
1083 * CreateCursor (USER32.@)
1085 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1086 INT xHotSpot, INT yHotSpot,
1087 INT nWidth, INT nHeight,
1088 LPCVOID lpANDbits, LPCVOID lpXORbits )
1090 CURSORICONINFO info;
1092 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1093 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1095 info.ptHotSpot.x = xHotSpot;
1096 info.ptHotSpot.y = yHotSpot;
1097 info.nWidth = nWidth;
1098 info.nHeight = nHeight;
1099 info.nWidthBytes = 0;
1101 info.bBitsPerPixel = 1;
1103 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1107 /***********************************************************************
1108 * CreateIcon (USER.407)
1110 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1111 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1112 LPCVOID lpANDbits, LPCVOID lpXORbits )
1114 CURSORICONINFO info;
1116 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1117 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1119 info.ptHotSpot.x = ICON_HOTSPOT;
1120 info.ptHotSpot.y = ICON_HOTSPOT;
1121 info.nWidth = nWidth;
1122 info.nHeight = nHeight;
1123 info.nWidthBytes = 0;
1124 info.bPlanes = bPlanes;
1125 info.bBitsPerPixel = bBitsPixel;
1127 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1131 /***********************************************************************
1132 * CreateIcon (USER32.@)
1134 * Creates an icon based on the specified bitmaps. The bitmaps must be
1135 * provided in a device dependent format and will be resized to
1136 * (SM_CXICON,SM_CYICON) and depth converted to match the screen's color
1137 * depth. The provided bitmaps must be top-down bitmaps.
1138 * Although Windows does not support 15bpp(*) this API must support it
1139 * for Winelib applications.
1141 * (*) Windows does not support 15bpp but it supports the 555 RGB 16bpp
1146 * - The provided bitmaps are not resized!
1147 * - The documentation says the lpXORbits bitmap must be in a device
1148 * dependent format. But we must still resize it and perform depth
1149 * conversions if necessary.
1150 * - I'm a bit unsure about the how the 'device dependent format' thing works.
1151 * I did some tests on windows and found that if you provide a 16bpp bitmap
1152 * in lpXORbits, then its format but be 565 RGB if the screen's bit depth
1153 * is 16bpp but it must be 555 RGB if the screen's bit depth is anything
1154 * else. I don't know if this is part of the GDI specs or if this is a
1155 * quirk of the graphics card driver.
1156 * - You may think that we check whether the bit depths match or not
1157 * as an optimization. But the truth is that the conversion using
1158 * CreateDIBitmap does not work for some bit depth (e.g. 8bpp) and I have
1160 * - I'm pretty sure that all the things we do in CreateIcon should
1161 * also be done in CreateIconIndirect...
1163 HICON WINAPI CreateIcon(
1164 HINSTANCE hInstance, /* [in] the application's hInstance, currently unused */
1165 INT nWidth, /* [in] the width of the provided bitmaps */
1166 INT nHeight, /* [in] the height of the provided bitmaps */
1167 BYTE bPlanes, /* [in] the number of planes in the provided bitmaps */
1168 BYTE bBitsPixel, /* [in] the number of bits per pixel of the lpXORbits bitmap */
1169 LPCVOID lpANDbits, /* [in] a monochrome bitmap representing the icon's mask */
1170 LPCVOID lpXORbits) /* [in] the icon's 'color' bitmap */
1175 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1176 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1182 if (GetDeviceCaps(hdc,BITSPIXEL)==bBitsPixel) {
1183 CURSORICONINFO info;
1185 info.ptHotSpot.x = ICON_HOTSPOT;
1186 info.ptHotSpot.y = ICON_HOTSPOT;
1187 info.nWidth = nWidth;
1188 info.nHeight = nHeight;
1189 info.nWidthBytes = 0;
1190 info.bPlanes = bPlanes;
1191 info.bBitsPerPixel = bBitsPixel;
1193 hIcon=CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1199 iinfo.xHotspot=ICON_HOTSPOT;
1200 iinfo.yHotspot=ICON_HOTSPOT;
1201 iinfo.hbmMask=CreateBitmap(nWidth,nHeight,1,1,lpANDbits);
1203 bmi.bmiHeader.biSize=sizeof(bmi.bmiHeader);
1204 bmi.bmiHeader.biWidth=nWidth;
1205 bmi.bmiHeader.biHeight=-nHeight;
1206 bmi.bmiHeader.biPlanes=bPlanes;
1207 bmi.bmiHeader.biBitCount=bBitsPixel;
1208 bmi.bmiHeader.biCompression=BI_RGB;
1209 bmi.bmiHeader.biSizeImage=0;
1210 bmi.bmiHeader.biXPelsPerMeter=0;
1211 bmi.bmiHeader.biYPelsPerMeter=0;
1212 bmi.bmiHeader.biClrUsed=0;
1213 bmi.bmiHeader.biClrImportant=0;
1215 iinfo.hbmColor = CreateDIBitmap( hdc, &bmi.bmiHeader,
1216 CBM_INIT, lpXORbits,
1217 &bmi, DIB_RGB_COLORS );
1219 hIcon=CreateIconIndirect(&iinfo);
1220 DeleteObject(iinfo.hbmMask);
1221 DeleteObject(iinfo.hbmColor);
1228 /***********************************************************************
1229 * CreateCursorIconIndirect (USER.408)
1231 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1232 CURSORICONINFO *info,
1238 int sizeAnd, sizeXor;
1240 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1241 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1242 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1243 sizeXor = info->nHeight * info->nWidthBytes;
1244 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1245 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1246 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1248 FarSetOwner16( handle, hInstance );
1249 ptr = (char *)GlobalLock16( handle );
1250 memcpy( ptr, info, sizeof(*info) );
1251 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1252 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1253 GlobalUnlock16( handle );
1258 /***********************************************************************
1259 * CopyIcon (USER.368)
1261 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1263 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1264 return CURSORICON_Copy( hInstance, hIcon );
1268 /***********************************************************************
1269 * CopyIcon (USER32.@)
1271 HICON WINAPI CopyIcon( HICON hIcon )
1273 TRACE_(icon)("%04x\n", hIcon );
1274 return CURSORICON_Copy( 0, hIcon );
1278 /***********************************************************************
1279 * CopyCursor (USER.369)
1281 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1283 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1284 return CURSORICON_Copy( hInstance, hCursor );
1287 /**********************************************************************
1288 * DestroyIcon32 (USER.610)
1290 * This routine is actually exported from Win95 USER under the name
1291 * DestroyIcon32 ... The behaviour implemented here should mimic
1292 * the Win95 one exactly, especially the return values, which
1293 * depend on the setting of various flags.
1295 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1299 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1301 /* Check whether destroying active cursor */
1303 if ( hActiveCursor == handle )
1305 ERR_(cursor)("Destroying active cursor!\n" );
1309 /* Try shared cursor/icon first */
1311 if ( !(flags & CID_NONSHARED) )
1313 INT count = CURSORICON_DelSharedIcon( handle );
1316 return (flags & CID_WIN32)? TRUE : (count == 0);
1318 /* FIXME: OEM cursors/icons should be recognized */
1321 /* Now assume non-shared cursor/icon */
1323 retv = GlobalFree16( handle );
1324 return (flags & CID_RESOURCE)? retv : TRUE;
1327 /***********************************************************************
1328 * DestroyIcon (USER.457)
1330 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1332 return CURSORICON_Destroy( hIcon, 0 );
1335 /***********************************************************************
1336 * DestroyIcon (USER32.@)
1338 BOOL WINAPI DestroyIcon( HICON hIcon )
1340 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1343 /***********************************************************************
1344 * DestroyCursor (USER.458)
1346 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1348 return CURSORICON_Destroy( hCursor, 0 );
1351 /***********************************************************************
1352 * DestroyCursor (USER32.@)
1354 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1356 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1360 /***********************************************************************
1361 * DrawIcon (USER.84)
1363 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1365 return DrawIcon( hdc, x, y, hIcon );
1369 /***********************************************************************
1370 * DrawIcon (USER32.@)
1372 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1374 CURSORICONINFO *ptr;
1376 HBITMAP hXorBits, hAndBits;
1377 COLORREF oldFg, oldBg;
1379 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1380 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1381 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1383 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1384 ptr->bBitsPerPixel, (char *)(ptr + 1)
1385 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1386 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1387 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1389 if (hXorBits && hAndBits)
1391 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1392 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1393 SelectObject( hMemDC, hXorBits );
1394 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1395 SelectObject( hMemDC, hBitTemp );
1398 if (hXorBits) DeleteObject( hXorBits );
1399 if (hAndBits) DeleteObject( hAndBits );
1400 GlobalUnlock16( hIcon );
1401 SetTextColor( hdc, oldFg );
1402 SetBkColor( hdc, oldBg );
1407 /***********************************************************************
1408 * IconSize (USER.86)
1410 * See "Undocumented Windows". Used by W2.0 paint.exe.
1412 DWORD WINAPI IconSize16( void )
1414 return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON));
1418 /***********************************************************************
1419 * DumpIcon (USER.459)
1421 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1422 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1424 CURSORICONINFO *info = MapSL( pInfo );
1425 int sizeAnd, sizeXor;
1427 if (!info) return 0;
1428 sizeXor = info->nHeight * info->nWidthBytes;
1429 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1430 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1431 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1432 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1433 return MAKELONG( sizeXor, sizeXor );
1437 /***********************************************************************
1438 * SetCursor (USER.69)
1440 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1442 return (HCURSOR16)SetCursor( hCursor );
1446 /***********************************************************************
1447 * SetCursor (USER32.@)
1449 * A handle to the previous cursor shape.
1451 HCURSOR WINAPI SetCursor(
1452 HCURSOR hCursor /* [in] Handle of cursor to show */
1456 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1457 TRACE_(cursor)("%04x\n", hCursor );
1458 hOldCursor = hActiveCursor;
1459 hActiveCursor = hCursor;
1460 /* Change the cursor shape only if it is visible */
1461 if (CURSOR_ShowCount >= 0)
1463 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1464 GlobalUnlock16( hActiveCursor );
1470 /***********************************************************************
1471 * SetCursorPos (USER.70)
1473 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1475 SetCursorPos( x, y );
1479 /***********************************************************************
1480 * SetCursorPos (USER32.@)
1482 BOOL WINAPI SetCursorPos( INT x, INT y )
1484 USER_Driver.pMoveCursor( x, y );
1489 /***********************************************************************
1490 * ShowCursor (USER.71)
1492 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1494 return ShowCursor( bShow );
1498 /***********************************************************************
1499 * ShowCursor (USER32.@)
1501 INT WINAPI ShowCursor( BOOL bShow )
1503 TRACE_(cursor)("%d, count=%d\n",
1504 bShow, CURSOR_ShowCount );
1508 if (++CURSOR_ShowCount == 0) /* Show it */
1510 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1511 GlobalUnlock16( hActiveCursor );
1516 if (--CURSOR_ShowCount == -1) /* Hide it */
1517 USER_Driver.pSetCursor( NULL );
1519 return CURSOR_ShowCount;
1523 /***********************************************************************
1524 * GetCursor (USER.247)
1526 HCURSOR16 WINAPI GetCursor16(void)
1528 return hActiveCursor;
1532 /***********************************************************************
1533 * GetCursor (USER32.@)
1535 HCURSOR WINAPI GetCursor(void)
1537 return hActiveCursor;
1541 /***********************************************************************
1542 * ClipCursor (USER.16)
1544 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1546 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1547 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1552 /***********************************************************************
1553 * ClipCursor (USER32.@)
1555 BOOL WINAPI ClipCursor( const RECT *rect )
1557 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1558 else CopyRect( &CURSOR_ClipRect, rect );
1563 /***********************************************************************
1564 * GetClipCursor (USER.309)
1566 void WINAPI GetClipCursor16( RECT16 *rect )
1568 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1572 /***********************************************************************
1573 * GetClipCursor (USER32.@)
1575 BOOL WINAPI GetClipCursor( RECT *rect )
1579 CopyRect( rect, &CURSOR_ClipRect );
1585 /**********************************************************************
1586 * LookupIconIdFromDirectoryEx (USER.364)
1588 * FIXME: exact parameter sizes
1590 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1591 INT16 width, INT16 height, UINT16 cFlag )
1593 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1595 if( dir && !dir->idReserved && (dir->idType & 3) )
1597 CURSORICONDIRENTRY* entry;
1602 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1605 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1610 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1612 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1614 if( entry ) retVal = entry->wResId;
1616 else WARN_(cursor)("invalid resource directory\n");
1620 /**********************************************************************
1621 * LookupIconIdFromDirectoryEx (USER32.@)
1623 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1624 INT width, INT height, UINT cFlag )
1626 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1629 /**********************************************************************
1630 * LookupIconIdFromDirectory (USER.???)
1632 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1634 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1635 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1636 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1639 /**********************************************************************
1640 * LookupIconIdFromDirectory (USER32.@)
1642 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1644 return LookupIconIdFromDirectoryEx( dir, bIcon,
1645 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1646 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1649 /**********************************************************************
1650 * GetIconID (USER.455)
1652 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1654 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1656 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1657 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1662 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1663 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1665 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1666 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1668 WARN_(cursor)("invalid res type %ld\n", resType );
1673 /**********************************************************************
1674 * LoadCursorIconHandler (USER.336)
1676 * Supposed to load resources of Windows 2.x applications.
1678 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1680 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1681 hResource, hModule, hRsrc);
1682 return (HGLOBAL16)0;
1685 /**********************************************************************
1686 * LoadDIBIconHandler (USER.357)
1688 * RT_ICON resource loader, installed by USER_SignalProc when module
1691 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1693 /* If hResource is zero we must allocate a new memory block, if it's
1694 * non-zero but GlobalLock() returns NULL then it was discarded and
1695 * we have to recommit some memory, otherwise we just need to check
1696 * the block size. See LoadProc() in 16-bit SDK for more.
1699 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1702 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1703 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1704 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1705 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1710 /**********************************************************************
1711 * LoadDIBCursorHandler (USER.356)
1713 * RT_CURSOR resource loader. Same as above.
1715 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1717 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1720 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1721 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1722 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1723 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1728 /**********************************************************************
1729 * LoadIconHandler (USER.456)
1731 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1733 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1735 TRACE_(cursor)("hRes=%04x\n",hResource);
1737 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1738 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1741 /***********************************************************************
1742 * LoadCursorW (USER32.@)
1744 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1746 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1747 LR_SHARED | LR_DEFAULTSIZE );
1750 /***********************************************************************
1751 * LoadCursorA (USER32.@)
1753 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1755 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1756 LR_SHARED | LR_DEFAULTSIZE );
1759 /***********************************************************************
1760 * LoadCursorFromFileW (USER32.@)
1762 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1764 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1765 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1768 /***********************************************************************
1769 * LoadCursorFromFileA (USER32.@)
1771 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1773 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1774 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1777 /***********************************************************************
1778 * LoadIconW (USER32.@)
1780 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1782 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1783 LR_SHARED | LR_DEFAULTSIZE );
1786 /***********************************************************************
1787 * LoadIconA (USER32.@)
1789 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1791 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1792 LR_SHARED | LR_DEFAULTSIZE );
1795 /**********************************************************************
1796 * GetIconInfo (USER.395)
1798 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1801 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1803 iconinfo->fIcon = ii32.fIcon;
1804 iconinfo->xHotspot = ii32.xHotspot;
1805 iconinfo->yHotspot = ii32.yHotspot;
1806 iconinfo->hbmMask = ii32.hbmMask;
1807 iconinfo->hbmColor = ii32.hbmColor;
1811 /**********************************************************************
1812 * GetIconInfo (USER32.@)
1814 BOOL WINAPI GetIconInfo(HICON hIcon,PICONINFO iconinfo) {
1815 CURSORICONINFO *ciconinfo;
1817 ciconinfo = GlobalLock16(hIcon);
1821 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1822 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1824 iconinfo->fIcon = TRUE;
1825 iconinfo->xHotspot = ciconinfo->nWidth / 2;
1826 iconinfo->yHotspot = ciconinfo->nHeight / 2;
1830 iconinfo->fIcon = FALSE;
1831 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1832 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1835 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1836 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1837 (char *)(ciconinfo + 1)
1838 + ciconinfo->nHeight *
1839 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1840 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1841 1, 1, (char *)(ciconinfo + 1));
1843 GlobalUnlock16(hIcon);
1848 /**********************************************************************
1849 * CreateIconIndirect (USER32.@)
1851 HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
1853 BITMAP bmpXor,bmpAnd;
1855 int sizeXor,sizeAnd;
1857 GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
1858 GetObjectA( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
1860 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
1861 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
1863 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1864 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1867 CURSORICONINFO *info;
1869 info = (CURSORICONINFO *)GlobalLock16( hObj );
1871 /* If we are creating an icon, the hotspot is unused */
1872 if (iconinfo->fIcon)
1874 info->ptHotSpot.x = ICON_HOTSPOT;
1875 info->ptHotSpot.y = ICON_HOTSPOT;
1879 info->ptHotSpot.x = iconinfo->xHotspot;
1880 info->ptHotSpot.y = iconinfo->yHotspot;
1883 info->nWidth = bmpXor.bmWidth;
1884 info->nHeight = bmpXor.bmHeight;
1885 info->nWidthBytes = bmpXor.bmWidthBytes;
1886 info->bPlanes = bmpXor.bmPlanes;
1887 info->bBitsPerPixel = bmpXor.bmBitsPixel;
1889 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1891 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1892 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1893 GlobalUnlock16( hObj );
1899 /**********************************************************************
1900 * DrawIconEx (USER.394)
1902 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1903 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1904 HBRUSH16 hbr, UINT16 flags)
1906 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1911 /******************************************************************************
1912 * DrawIconEx (USER32.@) Draws an icon or cursor on device context
1915 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1918 * hdc [I] Handle to device context
1919 * x0 [I] X coordinate of upper left corner
1920 * y0 [I] Y coordinate of upper left corner
1921 * hIcon [I] Handle to icon to draw
1922 * cxWidth [I] Width of icon
1923 * cyWidth [I] Height of icon
1924 * istep [I] Index of frame in animated cursor
1925 * hbr [I] Handle to background brush
1926 * flags [I] Icon-drawing flags
1932 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1933 INT cxWidth, INT cyWidth, UINT istep,
1934 HBRUSH hbr, UINT flags )
1936 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1937 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1938 BOOL result = FALSE, DoOffscreen;
1939 HBITMAP hB_off = 0, hOld = 0;
1941 if (!ptr) return FALSE;
1942 TRACE_(icon)("(hdc=%x,pos=%d.%d,hicon=%x,extend=%d.%d,istep=%d,br=%x,flags=0x%08x)\n",
1943 hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags
1947 FIXME_(icon)("Ignoring istep=%d\n", istep);
1948 if (flags & DI_COMPAT)
1949 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1952 FIXME_(icon)("no flags set? setting to DI_NORMAL\n");
1956 /* Calculate the size of the destination image. */
1959 if (flags & DI_DEFAULTSIZE)
1960 cxWidth = GetSystemMetrics (SM_CXICON);
1962 cxWidth = ptr->nWidth;
1966 if (flags & DI_DEFAULTSIZE)
1967 cyWidth = GetSystemMetrics (SM_CYICON);
1969 cyWidth = ptr->nHeight;
1972 DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
1982 hDC_off = CreateCompatibleDC(hdc);
1983 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1984 if (hDC_off && hB_off) {
1985 hOld = SelectObject(hDC_off, hB_off);
1986 FillRect(hDC_off, &r, hbr);
1990 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1992 HBITMAP hXorBits, hAndBits;
1993 COLORREF oldFg, oldBg;
1996 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1998 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1999 ptr->bPlanes, ptr->bBitsPerPixel,
2002 BITMAP_GetWidthBytes(ptr->nWidth,1) );
2003 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
2004 1, 1, (char *)(ptr+1) );
2005 oldFg = SetTextColor( hdc, RGB(0,0,0) );
2006 oldBg = SetBkColor( hdc, RGB(255,255,255) );
2008 if (hXorBits && hAndBits)
2010 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
2011 if (flags & DI_MASK)
2014 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
2015 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
2017 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
2018 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
2020 SelectObject( hMemDC, hXorBits );
2021 if (flags & DI_IMAGE)
2024 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
2025 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
2027 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
2028 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
2030 SelectObject( hMemDC, hBitTemp );
2034 SetTextColor( hdc, oldFg );
2035 SetBkColor( hdc, oldBg );
2036 if (hXorBits) DeleteObject( hXorBits );
2037 if (hAndBits) DeleteObject( hAndBits );
2038 SetStretchBltMode (hdc, nStretchMode);
2040 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2041 SelectObject(hDC_off, hOld);
2044 if (hMemDC) DeleteDC( hMemDC );
2045 if (hDC_off) DeleteDC(hDC_off);
2046 if (hB_off) DeleteObject(hB_off);
2047 GlobalUnlock16( hIcon );
2051 /***********************************************************************
2052 * DIB_FixColorsToLoadflags
2054 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
2057 static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
2060 COLORREF c_W, c_S, c_F, c_L, c_C;
2064 if (bmi->bmiHeader.biBitCount > 8) return;
2065 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
2066 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
2068 WARN_(resource)("Wrong bitmap header size!\n");
2071 colors = bmi->bmiHeader.biClrUsed;
2072 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
2073 colors = 1 << bmi->bmiHeader.biBitCount;
2074 c_W = GetSysColor(COLOR_WINDOW);
2075 c_S = GetSysColor(COLOR_3DSHADOW);
2076 c_F = GetSysColor(COLOR_3DFACE);
2077 c_L = GetSysColor(COLOR_3DLIGHT);
2078 if (loadflags & LR_LOADTRANSPARENT) {
2079 switch (bmi->bmiHeader.biBitCount) {
2080 case 1: pix = pix >> 7; break;
2081 case 4: pix = pix >> 4; break;
2084 WARN_(resource)("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
2087 if (pix >= colors) {
2088 WARN_(resource)("pixel has color index greater than biClrUsed!\n");
2091 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
2092 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
2093 ptr->rgbBlue = GetBValue(c_W);
2094 ptr->rgbGreen = GetGValue(c_W);
2095 ptr->rgbRed = GetRValue(c_W);
2097 if (loadflags & LR_LOADMAP3DCOLORS)
2098 for (i=0; i<colors; i++) {
2099 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2100 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2101 if (c_C == RGB(128, 128, 128)) {
2102 ptr->rgbRed = GetRValue(c_S);
2103 ptr->rgbGreen = GetGValue(c_S);
2104 ptr->rgbBlue = GetBValue(c_S);
2105 } else if (c_C == RGB(192, 192, 192)) {
2106 ptr->rgbRed = GetRValue(c_F);
2107 ptr->rgbGreen = GetGValue(c_F);
2108 ptr->rgbBlue = GetBValue(c_F);
2109 } else if (c_C == RGB(223, 223, 223)) {
2110 ptr->rgbRed = GetRValue(c_L);
2111 ptr->rgbGreen = GetGValue(c_L);
2112 ptr->rgbBlue = GetBValue(c_L);
2118 /**********************************************************************
2121 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2123 HBITMAP hbitmap = 0;
2127 BITMAPINFO *info, *fix_info=NULL;
2131 if (!(loadflags & LR_LOADFROMFILE)) {
2132 if (!instance) /* OEM bitmap */
2134 if (HIWORD((int)name)) return 0;
2135 return USER_Driver.pLoadOEMResource( LOWORD((int)name), OEM_BITMAP );
2138 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2139 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2141 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2145 if (!(ptr = map_fileW( name ))) return 0;
2146 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2148 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2149 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2153 memcpy(fix_info, info, size);
2154 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2155 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2156 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2159 char *bits = (char *)info + size;
2160 if (loadflags & LR_CREATEDIBSECTION) {
2162 hbitmap = CreateDIBSection(screen_dc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2163 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2164 SetDIBits(screen_dc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2168 hbitmap = CreateDIBitmap( screen_dc, &fix_info->bmiHeader, CBM_INIT,
2169 bits, fix_info, DIB_RGB_COLORS );
2175 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2180 /***********************************************************************
2181 * LoadImage (USER.389)
2184 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2185 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2187 return LoadImageA( hinst, name, type, desiredx, desiredy, loadflags );
2190 /**********************************************************************
2191 * LoadImageA (USER32.@)
2193 * FIXME: implementation lacks some features, see LR_ defines in windows.h
2196 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2197 INT desiredx, INT desiredy, UINT loadflags)
2202 if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
2203 else u_name=(LPWSTR)name;
2204 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2205 if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
2210 /******************************************************************************
2211 * LoadImageW (USER32.@) Loads an icon, cursor, or bitmap
2214 * hinst [I] Handle of instance that contains image
2215 * name [I] Name of image
2216 * type [I] Type of image
2217 * desiredx [I] Desired width
2218 * desiredy [I] Desired height
2219 * loadflags [I] Load flags
2222 * Success: Handle to newly loaded image
2225 * FIXME: Implementation lacks some features, see LR_ defines in windows.h
2227 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2228 INT desiredx, INT desiredy, UINT loadflags )
2231 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2232 hinst,name,type,desiredx,desiredy,loadflags);
2234 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2235 hinst,name,type,desiredx,desiredy,loadflags);
2237 if (loadflags & LR_DEFAULTSIZE) {
2238 if (type == IMAGE_ICON) {
2239 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2240 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2241 } else if (type == IMAGE_CURSOR) {
2242 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2243 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2246 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2249 return BITMAP_Load( hinst, name, loadflags );
2252 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2255 UINT palEnts = GetSystemPaletteEntries(screen_dc, 0, 0, NULL);
2256 if (palEnts == 0) palEnts = 256;
2257 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2258 palEnts, FALSE, loadflags);
2263 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2264 1, TRUE, loadflags);
2270 /******************************************************************************
2271 * CopyImage (USER.390) Creates new image and copies attributes to it
2274 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2275 INT16 desiredy, UINT16 flags )
2277 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2278 (INT)desiredy, (UINT)flags);
2281 /******************************************************************************
2282 * CopyImage (USER32.@) Creates new image and copies attributes to it
2285 * hnd [I] Handle to image to copy
2286 * type [I] Type of image to copy
2287 * desiredx [I] Desired width of new image
2288 * desiredy [I] Desired height of new image
2289 * flags [I] Copy flags
2292 * Success: Handle to newly created image
2295 * FIXME: implementation still lacks nearly all features, see LR_*
2296 * defines in windows.h
2298 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2299 INT desiredy, UINT flags )
2304 return BITMAP_CopyBitmap(hnd);
2306 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2308 /* Should call CURSORICON_ExtCopy but more testing
2309 * needs to be done before we change this
2311 return CopyCursor(hnd);
2317 /******************************************************************************
2318 * LoadBitmapW (USER32.@) Loads bitmap from the executable file
2321 * Success: Handle to specified bitmap
2324 HBITMAP WINAPI LoadBitmapW(
2325 HINSTANCE instance, /* [in] Handle to application instance */
2326 LPCWSTR name) /* [in] Address of bitmap resource name */
2328 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2331 /**********************************************************************
2332 * LoadBitmapA (USER32.@)
2334 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2336 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2339 /**********************************************************************
2340 * LoadBitmap (USER.175)
2342 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, LPCSTR name )
2344 return LoadBitmapA( instance, name );