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"
45 #include "debugtools.h"
52 DECLARE_DEBUG_CHANNEL(cursor);
53 DECLARE_DEBUG_CHANNEL(icon);
54 DECLARE_DEBUG_CHANNEL(resource);
56 static HCURSOR hActiveCursor = 0; /* Active cursor */
57 static INT CURSOR_ShowCount = 0; /* Cursor display count */
58 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
61 /**********************************************************************
62 * ICONCACHE for cursors/icons loaded with LR_SHARED.
64 * FIXME: This should not be allocated on the system heap, but on a
65 * subsystem-global heap (i.e. one for all Win16 processes,
66 * and one each for every Win32 process).
68 typedef struct tagICONCACHE
70 struct tagICONCACHE *next;
81 static ICONCACHE *IconAnchor = NULL;
82 static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT;
83 static WORD ICON_HOTSPOT = 0x4242;
85 /**********************************************************************
86 * CURSORICON_FindSharedIcon
88 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
93 EnterCriticalSection( &IconCrst );
95 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
96 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
103 LeaveCriticalSection( &IconCrst );
108 /*************************************************************************
109 * CURSORICON_FindCache
111 * Given a handle, find the coresponding cache element
114 * Handle [I] handle to an Image
117 * Success: The cache entry
121 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
124 ICONCACHE *pRet=NULL;
125 BOOL IsFound = FALSE;
128 EnterCriticalSection( &IconCrst );
130 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
132 if ( handle == ptr->handle )
139 LeaveCriticalSection( &IconCrst );
144 /**********************************************************************
145 * CURSORICON_AddSharedIcon
147 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
149 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
152 ptr->hModule = hModule;
154 ptr->handle = handle;
155 ptr->hGroupRsrc = hGroupRsrc;
158 EnterCriticalSection( &IconCrst );
159 ptr->next = IconAnchor;
161 LeaveCriticalSection( &IconCrst );
164 /**********************************************************************
165 * CURSORICON_DelSharedIcon
167 static INT CURSORICON_DelSharedIcon( HANDLE handle )
172 EnterCriticalSection( &IconCrst );
174 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
175 if ( ptr->handle == handle )
177 if ( ptr->count > 0 ) ptr->count--;
182 LeaveCriticalSection( &IconCrst );
187 /**********************************************************************
188 * CURSORICON_FreeModuleIcons
190 void CURSORICON_FreeModuleIcons( HMODULE hModule )
192 ICONCACHE **ptr = &IconAnchor;
194 if ( HIWORD( hModule ) )
195 hModule = MapHModuleLS( hModule );
197 hModule = GetExePtr( hModule );
199 EnterCriticalSection( &IconCrst );
203 if ( (*ptr)->hModule == hModule )
205 ICONCACHE *freePtr = *ptr;
206 *ptr = freePtr->next;
208 GlobalFree16( freePtr->handle );
209 HeapFree( SystemHeap, 0, freePtr );
215 LeaveCriticalSection( &IconCrst );
218 /**********************************************************************
219 * CURSORICON_FindBestIcon
221 * Find the icon closest to the requested size and number of colors.
223 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
224 int height, int colors )
227 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
228 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
229 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
231 if (dir->idCount < 1)
233 WARN_(icon)("Empty directory!\n" );
236 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
239 iTotalDiff = 0xFFFFFFFF;
240 iColorDiff = 0xFFFFFFFF;
241 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
243 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
244 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
246 if(iTotalDiff > (iTempXDiff + iTempYDiff))
250 iTotalDiff = iXDiff + iYDiff;
254 /* Find Best Colors for Best Fit */
255 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
257 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
258 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
260 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
261 if(iColorDiff > iTempColorDiff)
264 iColorDiff = iTempColorDiff;
273 /**********************************************************************
274 * CURSORICON_FindBestCursor
276 * Find the cursor closest to the requested size.
277 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
280 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
281 int width, int height, int color)
283 int i, maxwidth, maxheight;
284 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
286 if (dir->idCount < 1)
288 WARN_(cursor)("Empty directory!\n" );
291 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
293 /* Double height to account for AND and XOR masks */
297 /* First find the largest one smaller than or equal to the requested size*/
299 maxwidth = maxheight = 0;
300 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
301 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
302 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
303 (entry->wBitCount == 1))
306 maxwidth = entry->ResInfo.cursor.wWidth;
307 maxheight = entry->ResInfo.cursor.wHeight;
309 if (bestEntry) return bestEntry;
311 /* Now find the smallest one larger than the requested size */
313 maxwidth = maxheight = 255;
314 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
315 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
316 (entry->wBitCount == 1))
319 maxwidth = entry->ResInfo.cursor.wWidth;
320 maxheight = entry->ResInfo.cursor.wHeight;
326 /*********************************************************************
327 * The main purpose of this function is to create fake resource directory
328 * and fake resource entries. There are several reasons for this:
329 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
331 * There are some "bad" cursor files which do not have
332 * bColorCount initialized but instead one must read this info
333 * directly from corresponding DIB sections
334 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
336 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
337 CURSORICONDIR **res, LPBYTE **ptr)
340 CURSORICONFILEDIR *bits;
341 int entries, size, i;
345 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
347 /* FIXME: test for inimated icons
348 * hack to load the first icon from the *.ani file
350 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
351 { LPBYTE pos = (LPBYTE) bits;
352 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
355 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
356 { FIXME_(cursor)("icon entry found! %p\n", bits);
358 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
361 bits=(CURSORICONFILEDIR*)(pos+4);
362 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
366 if (pos>=(LPBYTE)bits+766) goto fail;
369 if (!(entries = bits->idCount)) goto fail;
370 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
371 _free = (LPBYTE) size;
373 for (i=0; i < entries; i++)
374 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
376 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
377 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
378 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
380 _free = (LPBYTE)(*res) + (int)_free;
381 memcpy((*res), bits, 6);
382 for (i=0; i<entries; i++)
384 ((LPBYTE*)(*ptr))[i] = _free;
386 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
387 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
388 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
389 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
390 _free+=sizeof(POINT16);
392 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
393 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
394 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
396 (*res)->idEntries[i].wPlanes=1;
397 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
398 bits->idEntries[i].dwDIBOffset))->biBitCount;
399 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
400 (*res)->idEntries[i].wResId=i+1;
402 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
403 (*res)->idEntries[i].dwBytesInRes);
404 _free += (*res)->idEntries[i].dwBytesInRes;
406 UnmapViewOfFile( bits );
409 if (*res) HeapFree( GetProcessHeap(), 0, *res );
410 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
411 UnmapViewOfFile( bits );
416 /**********************************************************************
417 * CURSORICON_CreateFromResource
419 * Create a cursor or icon from in-memory resource template.
421 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
422 * with cbSize parameter as well.
424 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
425 UINT cbSize, BOOL bIcon, DWORD dwVersion,
426 INT width, INT height, UINT loadflags )
428 int sizeAnd, sizeXor;
429 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
430 BITMAP bmpXor, bmpAnd;
437 hotspot.x = ICON_HOTSPOT;
438 hotspot.y = ICON_HOTSPOT;
440 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
441 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
442 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
443 if (dwVersion == 0x00020000)
445 FIXME_(cursor)("\t2.xx resources are not supported\n");
450 bmi = (BITMAPINFO *)bits;
451 else /* get the hotspot */
453 POINT16 *pt = (POINT16 *)bits;
455 bmi = (BITMAPINFO *)(pt + 1);
457 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
459 if (!width) width = bmi->bmiHeader.biWidth;
460 if (!height) height = bmi->bmiHeader.biHeight/2;
461 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
462 (bmi->bmiHeader.biWidth != width);
464 /* Check bitmap header */
466 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
467 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
468 bmi->bmiHeader.biCompression != BI_RGB) )
470 WARN_(cursor)("\tinvalid resource bitmap header.\n");
474 if( (hdc = GetDC( 0 )) )
478 /* Make sure we have room for the monochrome bitmap later on.
479 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
480 * up to and including the biBitCount. In-memory icon resource
481 * format is as follows:
483 * BITMAPINFOHEADER icHeader // DIB header
484 * RGBQUAD icColors[] // Color table
485 * BYTE icXOR[] // DIB bits for XOR mask
486 * BYTE icAND[] // DIB bits for AND mask
489 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
490 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
492 memcpy( pInfo, bmi, size );
493 pInfo->bmiHeader.biHeight /= 2;
495 /* Create the XOR bitmap */
500 hXorBits = CreateCompatibleBitmap(hdc, width, height);
504 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
509 HDC hMem = CreateCompatibleDC(hdc);
513 hOld = SelectObject(hMem, hXorBits);
514 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
515 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
516 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
517 SelectObject(hMem, hOld);
520 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
522 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
523 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
526 char* xbits = (char *)bmi + size +
527 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
528 bmi->bmiHeader.biHeight,
529 bmi->bmiHeader.biBitCount) / 2;
531 pInfo->bmiHeader.biBitCount = 1;
532 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
534 RGBQUAD *rgb = pInfo->bmiColors;
536 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
537 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
538 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
539 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
543 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
545 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
546 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
549 /* Create the AND bitmap */
552 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
554 HDC hMem = CreateCompatibleDC(hdc);
558 hOld = SelectObject(hMem, hAndBits);
559 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
560 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
561 xbits, pInfo, DIB_RGB_COLORS, SRCCOPY);
562 SelectObject(hMem, hOld);
565 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
567 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
568 CBM_INIT, xbits, pInfo, DIB_RGB_COLORS );
570 if( !hAndBits ) DeleteObject( hXorBits );
572 HeapFree( GetProcessHeap(), 0, pInfo );
577 if( !hXorBits || !hAndBits )
579 WARN_(cursor)("\tunable to create an icon bitmap.\n");
583 /* Now create the CURSORICONINFO structure */
584 GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor );
585 GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd );
586 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
587 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
589 if (hObj) hObj = GlobalReAlloc16( hObj,
590 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
591 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
592 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
595 CURSORICONINFO *info;
597 /* Make it owned by the module */
598 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
600 info = (CURSORICONINFO *)GlobalLock16( hObj );
601 info->ptHotSpot.x = hotspot.x;
602 info->ptHotSpot.y = hotspot.y;
603 info->nWidth = bmpXor.bmWidth;
604 info->nHeight = bmpXor.bmHeight;
605 info->nWidthBytes = bmpXor.bmWidthBytes;
606 info->bPlanes = bmpXor.bmPlanes;
607 info->bBitsPerPixel = bmpXor.bmBitsPixel;
609 /* Transfer the bitmap bits to the CURSORICONINFO structure */
611 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
612 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
613 GlobalUnlock16( hObj );
616 DeleteObject( hAndBits );
617 DeleteObject( hXorBits );
622 /**********************************************************************
623 * CreateIconFromResourceEx16 (USER.450)
625 * FIXME: not sure about exact parameter types
627 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
628 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
630 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
631 width, height, cFlag);
635 /**********************************************************************
636 * CreateIconFromResource (USER32.76)
638 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
639 BOOL bIcon, DWORD dwVersion)
641 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
645 /**********************************************************************
646 * CreateIconFromResourceEx (USER32.77)
648 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
649 BOOL bIcon, DWORD dwVersion,
650 INT width, INT height,
653 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
655 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
656 width, height, cFlag );
660 /**********************************************************************
663 * Load a cursor or icon from resource or file.
665 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
666 INT width, INT height, INT colors,
667 BOOL fCursor, UINT loadflags )
669 HANDLE handle = 0, h = 0;
672 CURSORICONDIRENTRY *dirEntry;
675 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
678 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
681 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
683 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
684 bits = ptr[dirEntry->wResId-1];
685 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
686 !fCursor, 0x00030000, width, height, loadflags);
687 HeapFree( GetProcessHeap(), 0, dir );
688 HeapFree( GetProcessHeap(), 0, ptr );
691 else if ( !hInstance ) /* Load OEM cursor/icon */
697 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
698 if( ansi[0]=='#') /*Check for '#xxx' name */
700 resid = atoi(ansi+1);
701 HeapFree( GetProcessHeap(), 0, ansi );
705 HeapFree( GetProcessHeap(), 0, ansi );
709 else resid = LOWORD(name);
710 h = USER_Driver.pLoadOEMResource( resid, fCursor ? OEM_CURSOR : OEM_ICON );
713 else /* Load from resource */
719 /* Normalize hInstance (must be uniquely represented for icon cache) */
721 if ( HIWORD( hInstance ) )
722 hInstance = MapHModuleLS( hInstance );
724 hInstance = GetExePtr( hInstance );
726 /* Get directory resource ID */
728 if (!(hRsrc = FindResourceW( hInstance, name,
729 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
733 /* Find the best entry in the directory */
735 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
736 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
738 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
741 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
742 width, height, colors );
743 if (!dirEntry) return 0;
744 wResId = dirEntry->wResId;
745 dwBytesInRes = dirEntry->dwBytesInRes;
746 FreeResource( handle );
748 /* Load the resource */
750 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
751 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
753 /* If shared icon, check whether it was already loaded */
754 if ( (loadflags & LR_SHARED)
755 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
758 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
759 bits = (LPBYTE)LockResource( handle );
760 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
761 !fCursor, 0x00030000, width, height, loadflags);
762 FreeResource( handle );
764 /* If shared icon, add to icon cache */
766 if ( h && (loadflags & LR_SHARED) )
767 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
773 /***********************************************************************
776 * Make a copy of a cursor or icon.
778 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
780 char *ptrOld, *ptrNew;
784 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
785 if (!(hInstance = GetExePtr( hInstance ))) return 0;
786 size = GlobalSize16( handle );
787 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
788 FarSetOwner16( hNew, hInstance );
789 ptrNew = (char *)GlobalLock16( hNew );
790 memcpy( ptrNew, ptrOld, size );
791 GlobalUnlock16( handle );
792 GlobalUnlock16( hNew );
796 /*************************************************************************
799 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
802 * Handle [I] handle to an Image
803 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
804 * iDesiredCX [I] The Desired width of the Image
805 * iDesiredCY [I] The desired height of the Image
806 * nFlags [I] The flags from CopyImage
809 * Success: The new handle of the Image
812 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
813 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
814 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
819 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
820 INT iDesiredCX, INT iDesiredCY,
825 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
826 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
833 /* Best Fit or Monochrome */
834 if( (nFlags & LR_COPYFROMRESOURCE
835 && (iDesiredCX > 0 || iDesiredCY > 0))
836 || nFlags & LR_MONOCHROME)
838 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
840 /* Not Found in Cache, then do a strait copy
842 if(pIconCache == NULL)
844 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
845 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
846 if(nFlags & LR_COPYFROMRESOURCE)
848 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
853 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
860 CURSORICONDIRENTRY *pDirEntry;
861 BOOL bIsIcon = (nType == IMAGE_ICON);
863 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
865 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
866 || (iDesiredCX == 0 && iDesiredCY == 0))
868 iDesiredCY = GetSystemMetrics(bIsIcon ?
869 SM_CYICON : SM_CYCURSOR);
870 iDesiredCX = GetSystemMetrics(bIsIcon ?
871 SM_CXICON : SM_CXCURSOR);
874 /* Retreive the CURSORICONDIRENTRY
876 if (!(hMem = LoadResource( pIconCache->hModule ,
877 pIconCache->hGroupRsrc)))
881 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
890 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
891 pDir, iDesiredCX, iDesiredCY, 256);
895 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
896 pDir, iDesiredCX, iDesiredCY, 1);
899 wResId = pDirEntry->wResId;
900 dwBytesInRes = pDirEntry->dwBytesInRes;
903 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
904 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
905 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
909 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
910 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
914 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
919 pBits = (LPBYTE)LockResource( hMem );
921 if(nFlags & LR_DEFAULTSIZE)
923 iTargetCY = GetSystemMetrics(SM_CYICON);
924 iTargetCX = GetSystemMetrics(SM_CXICON);
927 /* Create a New Icon with the proper dimension
929 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
930 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
936 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
937 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
942 /***********************************************************************
943 * CURSORICON_IconToCursor
945 * Converts bitmap to mono and truncates if icon is too large (should
946 * probably do StretchBlt() instead).
948 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
951 CURSORICONINFO *pIcon = NULL;
952 HTASK16 hTask = GetCurrentTask();
953 TDB* pTask = (TDB *)GlobalLock16(hTask);
956 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
957 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
959 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
962 pIcon = GlobalLock16(hRet);
964 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
966 GlobalUnlock16(hRet);
972 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
973 BYTE* psPtr, *pxbPtr = pXorBits;
974 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
979 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
980 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
982 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
983 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
984 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
986 memset(pXorBits, 0, 128);
987 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
988 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
989 cI.nWidth = 32; cI.nHeight = 32;
990 cI.nWidthBytes = 4; /* 32x1bpp */
992 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
993 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
995 for( iy = 0; iy < maxy; iy++ )
997 unsigned shift = iy % 2;
999 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
1000 (and_width > 4) ? 4 : and_width );
1001 for( ix = 0; ix < maxx; ix++ )
1003 if( bSemiTransparent && ((ix+shift)%2) )
1005 /* set AND bit, XOR bit stays 0 */
1007 pbc = pAndBits + iy * 4 + ix/8;
1008 *pbc |= 0x80 >> (ix%8);
1012 /* keep AND bit, set XOR bit */
1014 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1015 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1016 if(!PALETTE_Driver->pIsDark(val))
1018 pbc = pxbPtr + ix/8;
1019 *pbc |= 0x80 >> (ix%8);
1027 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
1029 if( !hRet ) /* fall back on default drag cursor */
1030 hRet = CURSORICON_Copy( pTask->hInstance ,
1031 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1032 GetSystemMetrics(SM_CXCURSOR),
1033 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1040 /***********************************************************************
1041 * LoadCursor16 (USER.173)
1043 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
1045 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1046 return LoadCursorA( hInstance, nameStr );
1050 /***********************************************************************
1051 * LoadIcon16 (USER.174)
1053 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
1055 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1056 return LoadIconA( hInstance, nameStr );
1060 /***********************************************************************
1061 * CreateCursor16 (USER.406)
1063 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1064 INT16 xHotSpot, INT16 yHotSpot,
1065 INT16 nWidth, INT16 nHeight,
1066 LPCVOID lpANDbits, LPCVOID lpXORbits )
1068 CURSORICONINFO info;
1070 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1071 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1073 info.ptHotSpot.x = xHotSpot;
1074 info.ptHotSpot.y = yHotSpot;
1075 info.nWidth = nWidth;
1076 info.nHeight = nHeight;
1077 info.nWidthBytes = 0;
1079 info.bBitsPerPixel = 1;
1081 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1085 /***********************************************************************
1086 * CreateCursor (USER32.67)
1088 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1089 INT xHotSpot, INT yHotSpot,
1090 INT nWidth, INT nHeight,
1091 LPCVOID lpANDbits, LPCVOID lpXORbits )
1093 CURSORICONINFO info;
1095 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1096 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1098 info.ptHotSpot.x = xHotSpot;
1099 info.ptHotSpot.y = yHotSpot;
1100 info.nWidth = nWidth;
1101 info.nHeight = nHeight;
1102 info.nWidthBytes = 0;
1104 info.bBitsPerPixel = 1;
1106 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1110 /***********************************************************************
1111 * CreateIcon16 (USER.407)
1113 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1114 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1115 LPCVOID lpANDbits, LPCVOID lpXORbits )
1117 CURSORICONINFO info;
1119 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1120 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1122 info.ptHotSpot.x = ICON_HOTSPOT;
1123 info.ptHotSpot.y = ICON_HOTSPOT;
1124 info.nWidth = nWidth;
1125 info.nHeight = nHeight;
1126 info.nWidthBytes = 0;
1127 info.bPlanes = bPlanes;
1128 info.bBitsPerPixel = bBitsPixel;
1130 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1134 /***********************************************************************
1135 * CreateIcon (USER32.75)
1137 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1138 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
1139 LPCVOID lpANDbits, LPCVOID lpXORbits )
1141 CURSORICONINFO info;
1143 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1144 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1146 info.ptHotSpot.x = ICON_HOTSPOT;
1147 info.ptHotSpot.y = ICON_HOTSPOT;
1148 info.nWidth = nWidth;
1149 info.nHeight = nHeight;
1150 info.nWidthBytes = 0;
1151 info.bPlanes = bPlanes;
1152 info.bBitsPerPixel = bBitsPixel;
1154 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1158 /***********************************************************************
1159 * CreateCursorIconIndirect (USER.408)
1161 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1162 CURSORICONINFO *info,
1168 int sizeAnd, sizeXor;
1170 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1171 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1172 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1173 sizeXor = info->nHeight * info->nWidthBytes;
1174 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1175 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1176 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1178 if (hInstance) FarSetOwner16( handle, hInstance );
1179 ptr = (char *)GlobalLock16( handle );
1180 memcpy( ptr, info, sizeof(*info) );
1181 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1182 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1183 GlobalUnlock16( handle );
1188 /***********************************************************************
1189 * CopyIcon16 (USER.368)
1191 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1193 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1194 return CURSORICON_Copy( hInstance, hIcon );
1198 /***********************************************************************
1199 * CopyIcon (USER32.60)
1201 HICON WINAPI CopyIcon( HICON hIcon )
1203 HTASK16 hTask = GetCurrentTask ();
1204 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1205 TRACE_(icon)("%04x\n", hIcon );
1206 return CURSORICON_Copy( pTask->hInstance, hIcon );
1210 /***********************************************************************
1211 * CopyCursor16 (USER.369)
1213 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1215 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1216 return CURSORICON_Copy( hInstance, hCursor );
1219 /**********************************************************************
1220 * CURSORICON_Destroy (USER.610)
1222 * This routine is actually exported from Win95 USER under the name
1223 * DestroyIcon32 ... The behaviour implemented here should mimic
1224 * the Win95 one exactly, especially the return values, which
1225 * depend on the setting of various flags.
1227 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1231 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1233 /* Check whether destroying active cursor */
1235 if ( hActiveCursor == handle )
1237 ERR_(cursor)("Destroying active cursor!\n" );
1241 /* Try shared cursor/icon first */
1243 if ( !(flags & CID_NONSHARED) )
1245 INT count = CURSORICON_DelSharedIcon( handle );
1248 return (flags & CID_WIN32)? TRUE : (count == 0);
1250 /* FIXME: OEM cursors/icons should be recognized */
1253 /* Now assume non-shared cursor/icon */
1255 retv = GlobalFree16( handle );
1256 return (flags & CID_RESOURCE)? retv : TRUE;
1259 /***********************************************************************
1260 * DestroyIcon16 (USER.457)
1262 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1264 return CURSORICON_Destroy( hIcon, 0 );
1267 /***********************************************************************
1268 * DestroyIcon (USER32.133)
1270 BOOL WINAPI DestroyIcon( HICON hIcon )
1272 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1275 /***********************************************************************
1276 * DestroyCursor16 (USER.458)
1278 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1280 return CURSORICON_Destroy( hCursor, 0 );
1283 /***********************************************************************
1284 * DestroyCursor (USER32.132)
1286 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1288 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1292 /***********************************************************************
1293 * DrawIcon16 (USER.84)
1295 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1297 return DrawIcon( hdc, x, y, hIcon );
1301 /***********************************************************************
1302 * DrawIcon (USER32.159)
1304 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1306 CURSORICONINFO *ptr;
1308 HBITMAP hXorBits, hAndBits;
1309 COLORREF oldFg, oldBg;
1311 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1312 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1313 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1315 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1316 ptr->bBitsPerPixel, (char *)(ptr + 1)
1317 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1318 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1319 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1321 if (hXorBits && hAndBits)
1323 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1324 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1325 SelectObject( hMemDC, hXorBits );
1326 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1327 SelectObject( hMemDC, hBitTemp );
1330 if (hXorBits) DeleteObject( hXorBits );
1331 if (hAndBits) DeleteObject( hAndBits );
1332 GlobalUnlock16( hIcon );
1333 SetTextColor( hdc, oldFg );
1334 SetBkColor( hdc, oldBg );
1339 /***********************************************************************
1340 * IconSize16 (USER.86)
1342 * See "Undocumented Windows". Used by W2.0 paint.exe.
1344 DWORD WINAPI IconSize16( void )
1346 return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON));
1350 /***********************************************************************
1351 * DumpIcon (USER.459)
1353 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1354 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1356 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1357 int sizeAnd, sizeXor;
1359 if (!info) return 0;
1360 sizeXor = info->nHeight * info->nWidthBytes;
1361 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1362 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1363 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1364 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1365 return MAKELONG( sizeXor, sizeXor );
1369 /***********************************************************************
1370 * SetCursor16 (USER.69)
1372 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1374 return (HCURSOR16)SetCursor( hCursor );
1378 /***********************************************************************
1379 * SetCursor (USER32.472)
1381 * A handle to the previous cursor shape.
1383 HCURSOR WINAPI SetCursor(
1384 HCURSOR hCursor /* Handle of cursor to show */
1388 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1389 TRACE_(cursor)("%04x\n", hCursor );
1390 hOldCursor = hActiveCursor;
1391 hActiveCursor = hCursor;
1392 /* Change the cursor shape only if it is visible */
1393 if (CURSOR_ShowCount >= 0)
1395 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1396 GlobalUnlock16( hActiveCursor );
1402 /***********************************************************************
1403 * SetCursorPos16 (USER.70)
1405 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1407 SetCursorPos( x, y );
1411 /***********************************************************************
1412 * SetCursorPos (USER32.474)
1414 BOOL WINAPI SetCursorPos( INT x, INT y )
1416 USER_Driver.pMoveCursor( x, y );
1421 /***********************************************************************
1422 * ShowCursor16 (USER.71)
1424 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1426 return ShowCursor( bShow );
1430 /***********************************************************************
1431 * ShowCursor (USER32.530)
1433 INT WINAPI ShowCursor( BOOL bShow )
1435 TRACE_(cursor)("%d, count=%d\n",
1436 bShow, CURSOR_ShowCount );
1440 if (++CURSOR_ShowCount == 0) /* Show it */
1442 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1443 GlobalUnlock16( hActiveCursor );
1448 if (--CURSOR_ShowCount == -1) /* Hide it */
1449 USER_Driver.pSetCursor( NULL );
1451 return CURSOR_ShowCount;
1455 /***********************************************************************
1456 * GetCursor16 (USER.247)
1458 HCURSOR16 WINAPI GetCursor16(void)
1460 return hActiveCursor;
1464 /***********************************************************************
1465 * GetCursor (USER32.227)
1467 HCURSOR WINAPI GetCursor(void)
1469 return hActiveCursor;
1473 /***********************************************************************
1474 * ClipCursor16 (USER.16)
1476 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1478 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1479 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1484 /***********************************************************************
1485 * ClipCursor (USER32.53)
1487 BOOL WINAPI ClipCursor( const RECT *rect )
1489 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1490 else CopyRect( &CURSOR_ClipRect, rect );
1495 /***********************************************************************
1496 * GetCursorPos16 (USER.17)
1498 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1505 TRACE_(cursor)("ret=%d,%d\n", pt->x, pt->y );
1510 /***********************************************************************
1511 * GetCursorPos (USER32.229)
1513 BOOL WINAPI GetCursorPos( POINT *pt )
1518 ret = GetCursorPos16( &pt16 );
1519 if (pt) CONV_POINT16TO32( &pt16, pt );
1520 return ((pt) ? ret : 0);
1524 /***********************************************************************
1525 * GetClipCursor16 (USER.309)
1527 void WINAPI GetClipCursor16( RECT16 *rect )
1529 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1533 /***********************************************************************
1534 * GetClipCursor (USER32.221)
1536 BOOL WINAPI GetClipCursor( RECT *rect )
1540 CopyRect( rect, &CURSOR_ClipRect );
1546 /**********************************************************************
1547 * LookupIconIdFromDirectoryEx16 (USER.364)
1549 * FIXME: exact parameter sizes
1551 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1552 INT16 width, INT16 height, UINT16 cFlag )
1554 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1556 if( dir && !dir->idReserved && (dir->idType & 3) )
1558 CURSORICONDIRENTRY* entry;
1563 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1566 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1571 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1573 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1575 if( entry ) retVal = entry->wResId;
1577 else WARN_(cursor)("invalid resource directory\n");
1581 /**********************************************************************
1582 * LookupIconIdFromDirectoryEx (USER32.380)
1584 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1585 INT width, INT height, UINT cFlag )
1587 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1590 /**********************************************************************
1591 * LookupIconIdFromDirectory (USER.???)
1593 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1595 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1596 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1597 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1600 /**********************************************************************
1601 * LookupIconIdFromDirectory (USER32.379)
1603 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1605 return LookupIconIdFromDirectoryEx( dir, bIcon,
1606 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1607 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1610 /**********************************************************************
1611 * GetIconID (USER.455)
1613 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1615 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1617 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1618 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1623 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1624 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1626 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1627 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1629 WARN_(cursor)("invalid res type %ld\n", resType );
1634 /**********************************************************************
1635 * LoadCursorIconHandler (USER.336)
1637 * Supposed to load resources of Windows 2.x applications.
1639 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1641 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1642 hResource, hModule, hRsrc);
1643 return (HGLOBAL16)0;
1646 /**********************************************************************
1647 * LoadDIBIconHandler (USER.357)
1649 * RT_ICON resource loader, installed by USER_SignalProc when module
1652 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1654 /* If hResource is zero we must allocate a new memory block, if it's
1655 * non-zero but GlobalLock() returns NULL then it was discarded and
1656 * we have to recommit some memory, otherwise we just need to check
1657 * the block size. See LoadProc() in 16-bit SDK for more.
1660 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1663 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1664 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1665 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1666 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1671 /**********************************************************************
1672 * LoadDIBCursorHandler (USER.356)
1674 * RT_CURSOR resource loader. Same as above.
1676 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1678 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1681 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1682 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1683 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1684 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1689 /**********************************************************************
1690 * LoadIconHandler (USER.456)
1692 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1694 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1696 TRACE_(cursor)("hRes=%04x\n",hResource);
1698 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1699 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1702 /***********************************************************************
1703 * LoadCursorW (USER32.362)
1705 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1707 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1708 LR_SHARED | LR_DEFAULTSIZE );
1711 /***********************************************************************
1712 * LoadCursorA (USER32.359)
1714 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1716 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1717 LR_SHARED | LR_DEFAULTSIZE );
1720 /***********************************************************************
1721 * LoadCursorFromFileW (USER32.361)
1723 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1725 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1726 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1729 /***********************************************************************
1730 * LoadCursorFromFileA (USER32.360)
1732 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1734 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1735 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1738 /***********************************************************************
1739 * LoadIconW (USER32.364)
1741 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1743 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1744 LR_SHARED | LR_DEFAULTSIZE );
1747 /***********************************************************************
1748 * LoadIconA (USER32.363)
1750 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1752 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1753 LR_SHARED | LR_DEFAULTSIZE );
1756 /**********************************************************************
1757 * GetIconInfo16 (USER.395)
1759 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1762 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1764 iconinfo->fIcon = ii32.fIcon;
1765 iconinfo->xHotspot = ii32.xHotspot;
1766 iconinfo->yHotspot = ii32.yHotspot;
1767 iconinfo->hbmMask = ii32.hbmMask;
1768 iconinfo->hbmColor = ii32.hbmColor;
1772 /**********************************************************************
1773 * GetIconInfo (USER32.242)
1775 BOOL WINAPI GetIconInfo(HICON hIcon,PICONINFO iconinfo) {
1776 CURSORICONINFO *ciconinfo;
1778 ciconinfo = GlobalLock16(hIcon);
1782 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1783 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1785 iconinfo->fIcon = TRUE;
1786 iconinfo->xHotspot = ciconinfo->nWidth / 2;
1787 iconinfo->yHotspot = ciconinfo->nHeight / 2;
1791 iconinfo->fIcon = FALSE;
1792 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1793 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1796 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1797 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1798 (char *)(ciconinfo + 1)
1799 + ciconinfo->nHeight *
1800 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1801 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1802 1, 1, (char *)(ciconinfo + 1));
1804 GlobalUnlock16(hIcon);
1809 /**********************************************************************
1810 * CreateIconIndirect (USER32.78)
1812 HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
1814 BITMAP bmpXor,bmpAnd;
1816 int sizeXor,sizeAnd;
1818 GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
1819 GetObjectA( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
1821 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
1822 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
1824 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1825 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1828 CURSORICONINFO *info;
1830 info = (CURSORICONINFO *)GlobalLock16( hObj );
1832 /* If we are creating an icon, the hotspot is unused */
1833 if (iconinfo->fIcon)
1835 info->ptHotSpot.x = ICON_HOTSPOT;
1836 info->ptHotSpot.y = ICON_HOTSPOT;
1840 info->ptHotSpot.x = iconinfo->xHotspot;
1841 info->ptHotSpot.y = iconinfo->yHotspot;
1844 info->nWidth = bmpXor.bmWidth;
1845 info->nHeight = bmpXor.bmHeight;
1846 info->nWidthBytes = bmpXor.bmWidthBytes;
1847 info->bPlanes = bmpXor.bmPlanes;
1848 info->bBitsPerPixel = bmpXor.bmBitsPixel;
1850 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1852 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1853 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1854 GlobalUnlock16( hObj );
1860 /**********************************************************************
1862 DrawIconEx16 (USER.394)
1864 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1865 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1866 HBRUSH16 hbr, UINT16 flags)
1868 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1873 /******************************************************************************
1874 * DrawIconEx [USER32.160] Draws an icon or cursor on device context
1877 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1880 * hdc [I] Handle to device context
1881 * x0 [I] X coordinate of upper left corner
1882 * y0 [I] Y coordinate of upper left corner
1883 * hIcon [I] Handle to icon to draw
1884 * cxWidth [I] Width of icon
1885 * cyWidth [I] Height of icon
1886 * istep [I] Index of frame in animated cursor
1887 * hbr [I] Handle to background brush
1888 * flags [I] Icon-drawing flags
1894 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1895 INT cxWidth, INT cyWidth, UINT istep,
1896 HBRUSH hbr, UINT flags )
1898 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1899 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1900 BOOL result = FALSE, DoOffscreen;
1901 HBITMAP hB_off = 0, hOld = 0;
1903 if (!ptr) return FALSE;
1906 FIXME_(icon)("Ignoring istep=%d\n", istep);
1907 if (flags & DI_COMPAT)
1908 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1910 /* Calculate the size of the destination image. */
1913 if (flags & DI_DEFAULTSIZE)
1914 cxWidth = GetSystemMetrics (SM_CXICON);
1916 cxWidth = ptr->nWidth;
1920 if (flags & DI_DEFAULTSIZE)
1921 cyWidth = GetSystemMetrics (SM_CYICON);
1923 cyWidth = ptr->nHeight;
1926 DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
1936 hDC_off = CreateCompatibleDC(hdc);
1937 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1938 if (hDC_off && hB_off) {
1939 hOld = SelectObject(hDC_off, hB_off);
1940 FillRect(hDC_off, &r, hbr);
1944 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1946 HBITMAP hXorBits, hAndBits;
1947 COLORREF oldFg, oldBg;
1950 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1952 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1953 ptr->bPlanes, ptr->bBitsPerPixel,
1956 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1957 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1958 1, 1, (char *)(ptr+1) );
1959 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1960 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1962 if (hXorBits && hAndBits)
1964 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1965 if (flags & DI_MASK)
1968 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1969 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1971 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1972 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1974 SelectObject( hMemDC, hXorBits );
1975 if (flags & DI_IMAGE)
1978 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1979 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1981 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1982 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1984 SelectObject( hMemDC, hBitTemp );
1988 SetTextColor( hdc, oldFg );
1989 SetBkColor( hdc, oldBg );
1990 if (hXorBits) DeleteObject( hXorBits );
1991 if (hAndBits) DeleteObject( hAndBits );
1992 SetStretchBltMode (hdc, nStretchMode);
1994 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1995 SelectObject(hDC_off, hOld);
1998 if (hMemDC) DeleteDC( hMemDC );
1999 if (hDC_off) DeleteDC(hDC_off);
2000 if (hB_off) DeleteObject(hB_off);
2001 GlobalUnlock16( hIcon );
2005 /***********************************************************************
2006 * DIB_FixColorsToLoadflags
2008 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
2011 static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
2014 COLORREF c_W, c_S, c_F, c_L, c_C;
2018 if (bmi->bmiHeader.biBitCount > 8) return;
2019 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
2020 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
2022 WARN_(resource)("Wrong bitmap header size!\n");
2025 colors = bmi->bmiHeader.biClrUsed;
2026 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
2027 colors = 1 << bmi->bmiHeader.biBitCount;
2028 c_W = GetSysColor(COLOR_WINDOW);
2029 c_S = GetSysColor(COLOR_3DSHADOW);
2030 c_F = GetSysColor(COLOR_3DFACE);
2031 c_L = GetSysColor(COLOR_3DLIGHT);
2032 if (loadflags & LR_LOADTRANSPARENT) {
2033 switch (bmi->bmiHeader.biBitCount) {
2034 case 1: pix = pix >> 7; break;
2035 case 4: pix = pix >> 4; break;
2038 WARN_(resource)("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
2041 if (pix >= colors) {
2042 WARN_(resource)("pixel has color index greater than biClrUsed!\n");
2045 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
2046 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
2047 ptr->rgbBlue = GetBValue(c_W);
2048 ptr->rgbGreen = GetGValue(c_W);
2049 ptr->rgbRed = GetRValue(c_W);
2051 if (loadflags & LR_LOADMAP3DCOLORS)
2052 for (i=0; i<colors; i++) {
2053 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2054 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2055 if (c_C == RGB(128, 128, 128)) {
2056 ptr->rgbRed = GetRValue(c_S);
2057 ptr->rgbGreen = GetGValue(c_S);
2058 ptr->rgbBlue = GetBValue(c_S);
2059 } else if (c_C == RGB(192, 192, 192)) {
2060 ptr->rgbRed = GetRValue(c_F);
2061 ptr->rgbGreen = GetGValue(c_F);
2062 ptr->rgbBlue = GetBValue(c_F);
2063 } else if (c_C == RGB(223, 223, 223)) {
2064 ptr->rgbRed = GetRValue(c_L);
2065 ptr->rgbGreen = GetGValue(c_L);
2066 ptr->rgbBlue = GetBValue(c_L);
2072 /**********************************************************************
2075 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2077 HBITMAP hbitmap = 0;
2082 BITMAPINFO *info, *fix_info=NULL;
2086 if (!(loadflags & LR_LOADFROMFILE)) {
2087 if (!instance) /* OEM bitmap */
2089 if (HIWORD((int)name)) return 0;
2090 return USER_Driver.pLoadOEMResource( LOWORD((int)name), OEM_BITMAP );
2093 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2094 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2096 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2100 if (!(ptr = (char *)VIRTUAL_MapFileW( name ))) return 0;
2101 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2103 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2104 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2108 memcpy(fix_info, info, size);
2109 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2110 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2111 if ((hdc = GetDC(0)) != 0) {
2112 char *bits = (char *)info + size;
2113 if (loadflags & LR_CREATEDIBSECTION) {
2115 hbitmap = CreateDIBSection(hdc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2116 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2117 SetDIBits(hdc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2121 hbitmap = CreateDIBitmap( hdc, &fix_info->bmiHeader, CBM_INIT,
2122 bits, fix_info, DIB_RGB_COLORS );
2124 ReleaseDC( 0, hdc );
2129 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2134 /***********************************************************************
2135 * LoadImage16 [USER.389]
2138 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2139 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2141 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2142 return LoadImageA( hinst, nameStr, type,
2143 desiredx, desiredy, loadflags );
2146 /**********************************************************************
2147 * LoadImageA (USER32.365)
2149 * FIXME: implementation lacks some features, see LR_ defines in windows.h
2152 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2153 INT desiredx, INT desiredy, UINT loadflags)
2158 if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
2159 else u_name=(LPWSTR)name;
2160 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2161 if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
2166 /******************************************************************************
2167 * LoadImageW [USER32.366] Loads an icon, cursor, or bitmap
2170 * hinst [I] Handle of instance that contains image
2171 * name [I] Name of image
2172 * type [I] Type of image
2173 * desiredx [I] Desired width
2174 * desiredy [I] Desired height
2175 * loadflags [I] Load flags
2178 * Success: Handle to newly loaded image
2181 * FIXME: Implementation lacks some features, see LR_ defines in windows.h
2183 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2184 INT desiredx, INT desiredy, UINT loadflags )
2187 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2188 hinst,name,type,desiredx,desiredy,loadflags);
2190 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2191 hinst,name,type,desiredx,desiredy,loadflags);
2193 if (loadflags & LR_DEFAULTSIZE) {
2194 if (type == IMAGE_ICON) {
2195 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2196 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2197 } else if (type == IMAGE_CURSOR) {
2198 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2199 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2202 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2205 return BITMAP_Load( hinst, name, loadflags );
2210 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
2215 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2216 palEnts, FALSE, loadflags);
2220 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2221 1, TRUE, loadflags);
2227 /******************************************************************************
2228 * CopyImage16 [USER.390] Creates new image and copies attributes to it
2231 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2232 INT16 desiredy, UINT16 flags )
2234 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2235 (INT)desiredy, (UINT)flags);
2238 /******************************************************************************
2239 * CopyImage [USER32.61] Creates new image and copies attributes to it
2242 * hnd [I] Handle to image to copy
2243 * type [I] Type of image to copy
2244 * desiredx [I] Desired width of new image
2245 * desiredy [I] Desired height of new image
2246 * flags [I] Copy flags
2249 * Success: Handle to newly created image
2252 * FIXME: implementation still lacks nearly all features, see LR_*
2253 * defines in windows.h
2255 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2256 INT desiredy, UINT flags )
2261 return BITMAP_CopyBitmap(hnd);
2263 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2265 /* Should call CURSORICON_ExtCopy but more testing
2266 * needs to be done before we change this
2268 return CopyCursor(hnd);
2274 /******************************************************************************
2275 * LoadBitmapW [USER32.358] Loads bitmap from the executable file
2278 * Success: Handle to specified bitmap
2281 HBITMAP WINAPI LoadBitmapW(
2282 HINSTANCE instance, /* [in] Handle to application instance */
2283 LPCWSTR name) /* [in] Address of bitmap resource name */
2285 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2288 /**********************************************************************
2289 * LoadBitmapA (USER32.357)
2291 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2293 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2296 /**********************************************************************
2297 * LoadBitmap16 (USER.175)
2299 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, SEGPTR name )
2301 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2302 return LoadBitmapA( instance, nameStr );