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"
47 #include "debugtools.h"
55 DECLARE_DEBUG_CHANNEL(cursor);
56 DECLARE_DEBUG_CHANNEL(icon);
57 DECLARE_DEBUG_CHANNEL(resource);
59 static HCURSOR hActiveCursor = 0; /* Active cursor */
60 static INT CURSOR_ShowCount = 0; /* Cursor display count */
61 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
64 /**********************************************************************
65 * ICONCACHE for cursors/icons loaded with LR_SHARED.
67 * FIXME: This should not be allocated on the system heap, but on a
68 * subsystem-global heap (i.e. one for all Win16 processes,
69 * and one each for every Win32 process).
71 typedef struct tagICONCACHE
73 struct tagICONCACHE *next;
84 static ICONCACHE *IconAnchor = NULL;
85 static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT;
86 static DWORD ICON_HOTSPOT = 0x42424242;
88 /**********************************************************************
89 * CURSORICON_FindSharedIcon
91 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
96 EnterCriticalSection( &IconCrst );
98 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
99 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
102 handle = ptr->handle;
106 LeaveCriticalSection( &IconCrst );
111 /*************************************************************************
112 * CURSORICON_FindCache
114 * Given a handle, find the coresponding cache element
117 * Handle [I] handle to an Image
120 * Success: The cache entry
124 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
127 ICONCACHE *pRet=NULL;
128 BOOL IsFound = FALSE;
131 EnterCriticalSection( &IconCrst );
133 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
135 if ( handle == ptr->handle )
142 LeaveCriticalSection( &IconCrst );
147 /**********************************************************************
148 * CURSORICON_AddSharedIcon
150 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
152 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
155 ptr->hModule = hModule;
157 ptr->handle = handle;
158 ptr->hGroupRsrc = hGroupRsrc;
161 EnterCriticalSection( &IconCrst );
162 ptr->next = IconAnchor;
164 LeaveCriticalSection( &IconCrst );
167 /**********************************************************************
168 * CURSORICON_DelSharedIcon
170 static INT CURSORICON_DelSharedIcon( HANDLE handle )
175 EnterCriticalSection( &IconCrst );
177 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
178 if ( ptr->handle == handle )
180 if ( ptr->count > 0 ) ptr->count--;
185 LeaveCriticalSection( &IconCrst );
190 /**********************************************************************
191 * CURSORICON_FreeModuleIcons
193 void CURSORICON_FreeModuleIcons( HMODULE hModule )
195 ICONCACHE **ptr = &IconAnchor;
197 if ( HIWORD( hModule ) )
198 hModule = MapHModuleLS( hModule );
200 hModule = GetExePtr( hModule );
202 EnterCriticalSection( &IconCrst );
206 if ( (*ptr)->hModule == hModule )
208 ICONCACHE *freePtr = *ptr;
209 *ptr = freePtr->next;
211 GlobalFree16( freePtr->handle );
212 HeapFree( SystemHeap, 0, freePtr );
218 LeaveCriticalSection( &IconCrst );
221 /**********************************************************************
222 * CURSORICON_FindBestIcon
224 * Find the icon closest to the requested size and number of colors.
226 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
227 int height, int colors )
230 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
231 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
232 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
234 if (dir->idCount < 1)
236 WARN_(icon)("Empty directory!\n" );
239 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
242 iTotalDiff = 0xFFFFFFFF;
243 iColorDiff = 0xFFFFFFFF;
244 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
246 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
247 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
249 if(iTotalDiff > (iTempXDiff + iTempYDiff))
253 iTotalDiff = iXDiff + iYDiff;
257 /* Find Best Colors for Best Fit */
258 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
260 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
261 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
263 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
264 if(iColorDiff > iTempColorDiff)
267 iColorDiff = iTempColorDiff;
276 /**********************************************************************
277 * CURSORICON_FindBestCursor
279 * Find the cursor closest to the requested size.
280 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
283 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
284 int width, int height, int color)
286 int i, maxwidth, maxheight;
287 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
289 if (dir->idCount < 1)
291 WARN_(cursor)("Empty directory!\n" );
294 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
296 /* Double height to account for AND and XOR masks */
300 /* First find the largest one smaller than or equal to the requested size*/
302 maxwidth = maxheight = 0;
303 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
304 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
305 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
306 (entry->wBitCount == 1))
309 maxwidth = entry->ResInfo.cursor.wWidth;
310 maxheight = entry->ResInfo.cursor.wHeight;
312 if (bestEntry) return bestEntry;
314 /* Now find the smallest one larger than the requested size */
316 maxwidth = maxheight = 255;
317 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
318 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
319 (entry->wBitCount == 1))
322 maxwidth = entry->ResInfo.cursor.wWidth;
323 maxheight = entry->ResInfo.cursor.wHeight;
329 /*********************************************************************
330 * The main purpose of this function is to create fake resource directory
331 * and fake resource entries. There are several reasons for this:
332 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
334 * There are some "bad" cursor files which do not have
335 * bColorCount initialized but instead one must read this info
336 * directly from corresponding DIB sections
337 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
339 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
340 CURSORICONDIR **res, LPBYTE **ptr)
343 CURSORICONFILEDIR *bits;
344 int entries, size, i;
348 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
350 /* FIXME: test for inimated icons
351 * hack to load the first icon from the *.ani file
353 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
354 { LPBYTE pos = (LPBYTE) bits;
355 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
358 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
359 { FIXME_(cursor)("icon entry found! %p\n", bits);
361 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
364 bits=(CURSORICONFILEDIR*)(pos+4);
365 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
369 if (pos>=(LPBYTE)bits+766) goto fail;
372 if (!(entries = bits->idCount)) goto fail;
373 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
374 _free = (LPBYTE) size;
376 for (i=0; i < entries; i++)
377 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
379 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
380 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
381 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
383 _free = (LPBYTE)(*res) + (int)_free;
384 memcpy((*res), bits, 6);
385 for (i=0; i<entries; i++)
387 ((LPBYTE*)(*ptr))[i] = _free;
389 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
390 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
391 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
392 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
393 _free+=sizeof(POINT16);
395 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
396 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
397 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
399 (*res)->idEntries[i].wPlanes=1;
400 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
401 bits->idEntries[i].dwDIBOffset))->biBitCount;
402 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
403 (*res)->idEntries[i].wResId=i+1;
405 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
406 (*res)->idEntries[i].dwBytesInRes);
407 _free += (*res)->idEntries[i].dwBytesInRes;
409 UnmapViewOfFile( bits );
412 if (*res) HeapFree( GetProcessHeap(), 0, *res );
413 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
414 UnmapViewOfFile( bits );
419 /**********************************************************************
420 * CURSORICON_CreateFromResource
422 * Create a cursor or icon from in-memory resource template.
424 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
425 * with cbSize parameter as well.
427 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
428 UINT cbSize, BOOL bIcon, DWORD dwVersion,
429 INT width, INT height, UINT loadflags )
431 int sizeAnd, sizeXor;
432 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
433 BITMAPOBJ *bmpXor, *bmpAnd;
440 hotspot.x = ICON_HOTSPOT;
441 hotspot.y = ICON_HOTSPOT;
443 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
444 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
445 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
446 if (dwVersion == 0x00020000)
448 FIXME_(cursor)("\t2.xx resources are not supported\n");
453 bmi = (BITMAPINFO *)bits;
454 else /* get the hotspot */
456 POINT16 *pt = (POINT16 *)bits;
458 bmi = (BITMAPINFO *)(pt + 1);
460 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
462 if (!width) width = bmi->bmiHeader.biWidth;
463 if (!height) height = bmi->bmiHeader.biHeight/2;
464 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
465 (bmi->bmiHeader.biWidth != width);
467 /* Check bitmap header */
469 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
470 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
471 bmi->bmiHeader.biCompression != BI_RGB) )
473 WARN_(cursor)("\tinvalid resource bitmap header.\n");
477 if( (hdc = GetDC( 0 )) )
481 /* Make sure we have room for the monochrome bitmap later on.
482 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
483 * up to and including the biBitCount. In-memory icon resource
484 * format is as follows:
486 * BITMAPINFOHEADER icHeader // DIB header
487 * RGBQUAD icColors[] // Color table
488 * BYTE icXOR[] // DIB bits for XOR mask
489 * BYTE icAND[] // DIB bits for AND mask
492 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
493 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
495 memcpy( pInfo, bmi, size );
496 pInfo->bmiHeader.biHeight /= 2;
498 /* Create the XOR bitmap */
503 hXorBits = CreateCompatibleBitmap(hdc, width, height);
507 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
512 HDC hMem = CreateCompatibleDC(hdc);
516 hOld = SelectObject(hMem, hXorBits);
517 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
518 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
519 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
520 SelectObject(hMem, hOld);
523 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
525 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
526 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
529 char* bits = (char *)bmi + size +
530 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
531 bmi->bmiHeader.biHeight,
532 bmi->bmiHeader.biBitCount) / 2;
534 pInfo->bmiHeader.biBitCount = 1;
535 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
537 RGBQUAD *rgb = pInfo->bmiColors;
539 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
540 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
541 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
542 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
546 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
548 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
549 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
552 /* Create the AND bitmap */
555 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
557 HDC hMem = CreateCompatibleDC(hdc);
561 hOld = SelectObject(hMem, hAndBits);
562 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
563 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
564 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
565 SelectObject(hMem, hOld);
568 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
570 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
571 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
573 if( !hAndBits ) DeleteObject( hXorBits );
575 HeapFree( GetProcessHeap(), 0, pInfo );
580 if( !hXorBits || !hAndBits )
582 WARN_(cursor)("\tunable to create an icon bitmap.\n");
586 /* Now create the CURSORICONINFO structure */
587 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
588 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
589 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
590 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
592 if (hObj) hObj = GlobalReAlloc16( hObj,
593 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
594 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
595 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
598 CURSORICONINFO *info;
600 /* Make it owned by the module */
601 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
603 info = (CURSORICONINFO *)GlobalLock16( hObj );
604 info->ptHotSpot.x = hotspot.x;
605 info->ptHotSpot.y = hotspot.y;
606 info->nWidth = bmpXor->bitmap.bmWidth;
607 info->nHeight = bmpXor->bitmap.bmHeight;
608 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
609 info->bPlanes = bmpXor->bitmap.bmPlanes;
610 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
612 /* Transfer the bitmap bits to the CURSORICONINFO structure */
614 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
615 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
616 GlobalUnlock16( hObj );
619 DeleteObject( hXorBits );
620 DeleteObject( hAndBits );
625 /**********************************************************************
626 * CreateIconFromResourceEx16 (USER.450)
628 * FIXME: not sure about exact parameter types
630 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
631 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
633 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
634 width, height, cFlag);
638 /**********************************************************************
639 * CreateIconFromResource (USER32.76)
641 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
642 BOOL bIcon, DWORD dwVersion)
644 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
648 /**********************************************************************
649 * CreateIconFromResourceEx (USER32.77)
651 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
652 BOOL bIcon, DWORD dwVersion,
653 INT width, INT height,
656 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
658 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
659 width, height, cFlag );
663 /**********************************************************************
666 * Load a cursor or icon from resource or file.
668 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
669 INT width, INT height, INT colors,
670 BOOL fCursor, UINT loadflags )
672 HANDLE handle = 0, h = 0;
675 CURSORICONDIRENTRY *dirEntry;
678 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
681 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
684 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
686 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
687 bits = ptr[dirEntry->wResId-1];
688 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
689 !fCursor, 0x00030000, width, height, loadflags);
690 HeapFree( GetProcessHeap(), 0, dir );
691 HeapFree( GetProcessHeap(), 0, ptr );
694 else if ( !hInstance ) /* Load OEM cursor/icon */
701 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
702 if( ansi[0]=='#') /*Check for '#xxx' name */
704 resid = atoi(ansi+1);
705 HeapFree( GetProcessHeap(), 0, ansi );
709 HeapFree( GetProcessHeap(), 0, ansi );
713 else resid = LOWORD(name);
714 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
716 DC *dc = DC_GetDCPtr( hdc );
717 if (dc->funcs->pLoadOEMResource)
718 h = dc->funcs->pLoadOEMResource( resid, fCursor ? OEM_CURSOR : OEM_ICON );
719 GDI_HEAP_UNLOCK( hdc );
724 else /* Load from resource */
730 /* Normalize hInstance (must be uniquely represented for icon cache) */
732 if ( HIWORD( hInstance ) )
733 hInstance = MapHModuleLS( hInstance );
735 hInstance = GetExePtr( hInstance );
737 /* Get directory resource ID */
739 if (!(hRsrc = FindResourceW( hInstance, name,
740 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
743 /* If shared icon, check whether it was already loaded */
745 if ( (loadflags & LR_SHARED)
746 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
749 /* Find the best entry in the directory */
751 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
752 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
754 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
757 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
758 width, height, colors );
759 if (!dirEntry) return 0;
760 wResId = dirEntry->wResId;
761 dwBytesInRes = dirEntry->dwBytesInRes;
762 FreeResource( handle );
764 /* Load the resource */
766 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
767 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
768 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
769 bits = (LPBYTE)LockResource( handle );
770 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
771 !fCursor, 0x00030000, width, height, loadflags);
772 FreeResource( handle );
774 /* If shared icon, add to icon cache */
776 if ( h && (loadflags & LR_SHARED) )
777 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
783 /***********************************************************************
786 * Make a copy of a cursor or icon.
788 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
790 char *ptrOld, *ptrNew;
794 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
795 if (!(hInstance = GetExePtr( hInstance ))) return 0;
796 size = GlobalSize16( handle );
797 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
798 FarSetOwner16( hNew, hInstance );
799 ptrNew = (char *)GlobalLock16( hNew );
800 memcpy( ptrNew, ptrOld, size );
801 GlobalUnlock16( handle );
802 GlobalUnlock16( hNew );
806 /*************************************************************************
809 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
812 * Handle [I] handle to an Image
813 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
814 * iDesiredCX [I] The Desired width of the Image
815 * iDesiredCY [I] The desired height of the Image
816 * nFlags [I] The flags from CopyImage
819 * Success: The new handle of the Image
822 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
823 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
824 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
829 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
830 INT iDesiredCX, INT iDesiredCY,
835 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
836 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
843 /* Best Fit or Monochrome */
844 if( (nFlags & LR_COPYFROMRESOURCE
845 && (iDesiredCX > 0 || iDesiredCY > 0))
846 || nFlags & LR_MONOCHROME)
848 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
850 /* Not Found in Cache, then do a strait copy
852 if(pIconCache == NULL)
854 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
855 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
856 if(nFlags & LR_COPYFROMRESOURCE)
858 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
863 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
870 CURSORICONDIRENTRY *pDirEntry;
871 BOOL bIsIcon = (nType == IMAGE_ICON);
873 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
875 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
876 || (iDesiredCX == 0 && iDesiredCY == 0))
878 iDesiredCY = GetSystemMetrics(bIsIcon ?
879 SM_CYICON : SM_CYCURSOR);
880 iDesiredCX = GetSystemMetrics(bIsIcon ?
881 SM_CXICON : SM_CXCURSOR);
884 /* Retreive the CURSORICONDIRENTRY
886 if (!(hMem = LoadResource( pIconCache->hModule ,
887 pIconCache->hGroupRsrc)))
891 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
900 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
901 pDir, iDesiredCX, iDesiredCY, 256);
905 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
906 pDir, iDesiredCX, iDesiredCY, 1);
909 wResId = pDirEntry->wResId;
910 dwBytesInRes = pDirEntry->dwBytesInRes;
913 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
914 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
915 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
919 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
920 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
924 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
929 pBits = (LPBYTE)LockResource( hMem );
931 if(nFlags & LR_DEFAULTSIZE)
933 iTargetCY = GetSystemMetrics(SM_CYICON);
934 iTargetCX = GetSystemMetrics(SM_CXICON);
937 /* Create a New Icon with the proper dimension
939 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
940 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
946 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
947 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
952 /***********************************************************************
953 * CURSORICON_IconToCursor
955 * Converts bitmap to mono and truncates if icon is too large (should
956 * probably do StretchBlt() instead).
958 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
961 CURSORICONINFO *pIcon = NULL;
962 HTASK16 hTask = GetCurrentTask();
963 TDB* pTask = (TDB *)GlobalLock16(hTask);
966 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
967 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
969 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
972 pIcon = GlobalLock16(hRet);
974 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
976 GlobalUnlock16(hRet);
982 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
983 BYTE* psPtr, *pxbPtr = pXorBits;
984 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
989 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
990 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
992 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
993 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
994 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
996 memset(pXorBits, 0, 128);
997 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
998 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
999 cI.nWidth = 32; cI.nHeight = 32;
1000 cI.nWidthBytes = 4; /* 32x1bpp */
1002 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
1003 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
1005 for( iy = 0; iy < maxy; iy++ )
1007 unsigned shift = iy % 2;
1009 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
1010 (and_width > 4) ? 4 : and_width );
1011 for( ix = 0; ix < maxx; ix++ )
1013 if( bSemiTransparent && ((ix+shift)%2) )
1015 /* set AND bit, XOR bit stays 0 */
1017 pbc = pAndBits + iy * 4 + ix/8;
1018 *pbc |= 0x80 >> (ix%8);
1022 /* keep AND bit, set XOR bit */
1024 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1025 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1026 if(!PALETTE_Driver->pIsDark(val))
1028 pbc = pxbPtr + ix/8;
1029 *pbc |= 0x80 >> (ix%8);
1037 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
1039 if( !hRet ) /* fall back on default drag cursor */
1040 hRet = CURSORICON_Copy( pTask->hInstance ,
1041 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1042 GetSystemMetrics(SM_CXCURSOR),
1043 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1050 /***********************************************************************
1051 * LoadCursor16 (USER.173)
1053 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
1055 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1056 return LoadCursorA( hInstance, nameStr );
1060 /***********************************************************************
1061 * LoadIcon16 (USER.174)
1063 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
1065 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1066 return LoadIconA( hInstance, nameStr );
1070 /***********************************************************************
1071 * CreateCursor16 (USER.406)
1073 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1074 INT16 xHotSpot, INT16 yHotSpot,
1075 INT16 nWidth, INT16 nHeight,
1076 LPCVOID lpANDbits, LPCVOID lpXORbits )
1078 CURSORICONINFO info;
1080 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1081 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1083 info.ptHotSpot.x = xHotSpot;
1084 info.ptHotSpot.y = yHotSpot;
1085 info.nWidth = nWidth;
1086 info.nHeight = nHeight;
1087 info.nWidthBytes = 0;
1089 info.bBitsPerPixel = 1;
1091 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1095 /***********************************************************************
1096 * CreateCursor (USER32.67)
1098 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1099 INT xHotSpot, INT yHotSpot,
1100 INT nWidth, INT nHeight,
1101 LPCVOID lpANDbits, LPCVOID lpXORbits )
1103 CURSORICONINFO info;
1105 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1106 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1108 info.ptHotSpot.x = xHotSpot;
1109 info.ptHotSpot.y = yHotSpot;
1110 info.nWidth = nWidth;
1111 info.nHeight = nHeight;
1112 info.nWidthBytes = 0;
1114 info.bBitsPerPixel = 1;
1116 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1120 /***********************************************************************
1121 * CreateIcon16 (USER.407)
1123 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1124 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1125 LPCVOID lpANDbits, LPCVOID lpXORbits )
1127 CURSORICONINFO info;
1129 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1130 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1132 info.ptHotSpot.x = ICON_HOTSPOT;
1133 info.ptHotSpot.y = ICON_HOTSPOT;
1134 info.nWidth = nWidth;
1135 info.nHeight = nHeight;
1136 info.nWidthBytes = 0;
1137 info.bPlanes = bPlanes;
1138 info.bBitsPerPixel = bBitsPixel;
1140 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1144 /***********************************************************************
1145 * CreateIcon (USER32.75)
1147 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1148 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
1149 LPCVOID lpANDbits, LPCVOID lpXORbits )
1151 CURSORICONINFO info;
1153 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1154 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1156 info.ptHotSpot.x = ICON_HOTSPOT;
1157 info.ptHotSpot.y = ICON_HOTSPOT;
1158 info.nWidth = nWidth;
1159 info.nHeight = nHeight;
1160 info.nWidthBytes = 0;
1161 info.bPlanes = bPlanes;
1162 info.bBitsPerPixel = bBitsPixel;
1164 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1168 /***********************************************************************
1169 * CreateCursorIconIndirect (USER.408)
1171 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1172 CURSORICONINFO *info,
1178 int sizeAnd, sizeXor;
1180 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1181 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1182 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1183 sizeXor = info->nHeight * info->nWidthBytes;
1184 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1185 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1186 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1188 if (hInstance) FarSetOwner16( handle, hInstance );
1189 ptr = (char *)GlobalLock16( handle );
1190 memcpy( ptr, info, sizeof(*info) );
1191 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1192 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1193 GlobalUnlock16( handle );
1198 /***********************************************************************
1199 * CopyIcon16 (USER.368)
1201 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1203 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1204 return CURSORICON_Copy( hInstance, hIcon );
1208 /***********************************************************************
1209 * CopyIcon (USER32.60)
1211 HICON WINAPI CopyIcon( HICON hIcon )
1213 HTASK16 hTask = GetCurrentTask ();
1214 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1215 TRACE_(icon)("%04x\n", hIcon );
1216 return CURSORICON_Copy( pTask->hInstance, hIcon );
1220 /***********************************************************************
1221 * CopyCursor16 (USER.369)
1223 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1225 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1226 return CURSORICON_Copy( hInstance, hCursor );
1229 /**********************************************************************
1230 * CURSORICON_Destroy (USER.610)
1232 * This routine is actually exported from Win95 USER under the name
1233 * DestroyIcon32 ... The behaviour implemented here should mimic
1234 * the Win95 one exactly, especially the return values, which
1235 * depend on the setting of various flags.
1237 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1241 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1243 /* Check whether destroying active cursor */
1245 if ( hActiveCursor == handle )
1247 ERR_(cursor)("Destroying active cursor!\n" );
1251 /* Try shared cursor/icon first */
1253 if ( !(flags & CID_NONSHARED) )
1255 INT count = CURSORICON_DelSharedIcon( handle );
1258 return (flags & CID_WIN32)? TRUE : (count == 0);
1260 /* FIXME: OEM cursors/icons should be recognized */
1263 /* Now assume non-shared cursor/icon */
1265 retv = GlobalFree16( handle );
1266 return (flags & CID_RESOURCE)? retv : TRUE;
1269 /***********************************************************************
1270 * DestroyIcon16 (USER.457)
1272 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1274 return CURSORICON_Destroy( hIcon, 0 );
1277 /***********************************************************************
1278 * DestroyIcon (USER32.133)
1280 BOOL WINAPI DestroyIcon( HICON hIcon )
1282 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1285 /***********************************************************************
1286 * DestroyCursor16 (USER.458)
1288 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1290 return CURSORICON_Destroy( hCursor, 0 );
1293 /***********************************************************************
1294 * DestroyCursor (USER32.132)
1296 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1298 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1302 /***********************************************************************
1303 * DrawIcon16 (USER.84)
1305 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1307 return DrawIcon( hdc, x, y, hIcon );
1311 /***********************************************************************
1312 * DrawIcon (USER32.159)
1314 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1316 CURSORICONINFO *ptr;
1318 HBITMAP hXorBits, hAndBits;
1319 COLORREF oldFg, oldBg;
1321 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1322 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1323 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1325 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1326 ptr->bBitsPerPixel, (char *)(ptr + 1)
1327 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1328 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1329 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1331 if (hXorBits && hAndBits)
1333 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1334 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1335 SelectObject( hMemDC, hXorBits );
1336 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1337 SelectObject( hMemDC, hBitTemp );
1340 if (hXorBits) DeleteObject( hXorBits );
1341 if (hAndBits) DeleteObject( hAndBits );
1342 GlobalUnlock16( hIcon );
1343 SetTextColor( hdc, oldFg );
1344 SetBkColor( hdc, oldBg );
1349 /***********************************************************************
1350 * DumpIcon (USER.459)
1352 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1353 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1355 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1356 int sizeAnd, sizeXor;
1358 if (!info) return 0;
1359 sizeXor = info->nHeight * info->nWidthBytes;
1360 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1361 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1362 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1363 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1364 return MAKELONG( sizeXor, sizeXor );
1368 /***********************************************************************
1369 * SetCursor16 (USER.69)
1371 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1373 return (HCURSOR16)SetCursor( hCursor );
1377 /***********************************************************************
1378 * SetCursor (USER32.472)
1380 * A handle to the previous cursor shape.
1382 HCURSOR WINAPI SetCursor(
1383 HCURSOR hCursor /* Handle of cursor to show */
1387 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1388 TRACE_(cursor)("%04x\n", hCursor );
1389 hOldCursor = hActiveCursor;
1390 hActiveCursor = hCursor;
1391 /* Change the cursor shape only if it is visible */
1392 if (CURSOR_ShowCount >= 0)
1394 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1395 GlobalUnlock16( hActiveCursor );
1401 /***********************************************************************
1402 * SetCursorPos16 (USER.70)
1404 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1406 SetCursorPos( x, y );
1410 /***********************************************************************
1411 * SetCursorPos (USER32.474)
1413 BOOL WINAPI SetCursorPos( INT x, INT y )
1415 DISPLAY_MoveCursor( x, y );
1420 /***********************************************************************
1421 * ShowCursor16 (USER.71)
1423 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1425 return ShowCursor( bShow );
1429 /***********************************************************************
1430 * ShowCursor (USER32.530)
1432 INT WINAPI ShowCursor( BOOL bShow )
1434 TRACE_(cursor)("%d, count=%d\n",
1435 bShow, CURSOR_ShowCount );
1439 if (++CURSOR_ShowCount == 0) /* Show it */
1441 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1442 GlobalUnlock16( hActiveCursor );
1447 if (--CURSOR_ShowCount == -1) /* Hide it */
1448 DISPLAY_SetCursor( NULL );
1450 return CURSOR_ShowCount;
1454 /***********************************************************************
1455 * GetCursor16 (USER.247)
1457 HCURSOR16 WINAPI GetCursor16(void)
1459 return hActiveCursor;
1463 /***********************************************************************
1464 * GetCursor (USER32.227)
1466 HCURSOR WINAPI GetCursor(void)
1468 return hActiveCursor;
1472 /***********************************************************************
1473 * ClipCursor16 (USER.16)
1475 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1477 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1478 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1483 /***********************************************************************
1484 * ClipCursor (USER32.53)
1486 BOOL WINAPI ClipCursor( const RECT *rect )
1488 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1489 else CopyRect( &CURSOR_ClipRect, rect );
1494 /***********************************************************************
1495 * GetCursorPos16 (USER.17)
1497 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1504 TRACE_(cursor)("ret=%d,%d\n", pt->x, pt->y );
1509 /***********************************************************************
1510 * GetCursorPos (USER32.229)
1512 BOOL WINAPI GetCursorPos( POINT *pt )
1517 ret = GetCursorPos16( &pt16 );
1518 if (pt) CONV_POINT16TO32( &pt16, pt );
1519 return ((pt) ? ret : 0);
1523 /***********************************************************************
1524 * GetClipCursor16 (USER.309)
1526 void WINAPI GetClipCursor16( RECT16 *rect )
1528 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1532 /***********************************************************************
1533 * GetClipCursor (USER32.221)
1535 BOOL WINAPI GetClipCursor( RECT *rect )
1539 CopyRect( rect, &CURSOR_ClipRect );
1545 /**********************************************************************
1546 * LookupIconIdFromDirectoryEx16 (USER.364)
1548 * FIXME: exact parameter sizes
1550 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1551 INT16 width, INT16 height, UINT16 cFlag )
1553 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1555 if( dir && !dir->idReserved && (dir->idType & 3) )
1557 CURSORICONDIRENTRY* entry;
1562 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1565 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1570 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1572 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1574 if( entry ) retVal = entry->wResId;
1576 else WARN_(cursor)("invalid resource directory\n");
1580 /**********************************************************************
1581 * LookupIconIdFromDirectoryEx (USER32.380)
1583 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1584 INT width, INT height, UINT cFlag )
1586 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1589 /**********************************************************************
1590 * LookupIconIdFromDirectory (USER.???)
1592 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1594 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1595 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1596 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1599 /**********************************************************************
1600 * LookupIconIdFromDirectory (USER32.379)
1602 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1604 return LookupIconIdFromDirectoryEx( dir, bIcon,
1605 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1606 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1609 /**********************************************************************
1610 * GetIconID (USER.455)
1612 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1614 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1616 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1617 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1622 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1623 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1625 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1626 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1628 WARN_(cursor)("invalid res type %ld\n", resType );
1633 /**********************************************************************
1634 * LoadCursorIconHandler (USER.336)
1636 * Supposed to load resources of Windows 2.x applications.
1638 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1640 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1641 hResource, hModule, hRsrc);
1642 return (HGLOBAL16)0;
1645 /**********************************************************************
1646 * LoadDIBIconHandler (USER.357)
1648 * RT_ICON resource loader, installed by USER_SignalProc when module
1651 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1653 /* If hResource is zero we must allocate a new memory block, if it's
1654 * non-zero but GlobalLock() returns NULL then it was discarded and
1655 * we have to recommit some memory, otherwise we just need to check
1656 * the block size. See LoadProc() in 16-bit SDK for more.
1659 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1662 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1663 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1664 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1665 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1670 /**********************************************************************
1671 * LoadDIBCursorHandler (USER.356)
1673 * RT_CURSOR resource loader. Same as above.
1675 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1677 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1680 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1681 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1682 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1683 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1688 /**********************************************************************
1689 * LoadIconHandler (USER.456)
1691 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1693 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1695 TRACE_(cursor)("hRes=%04x\n",hResource);
1697 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1698 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1701 /***********************************************************************
1702 * LoadCursorW (USER32.362)
1704 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1706 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1707 LR_SHARED | LR_DEFAULTSIZE );
1710 /***********************************************************************
1711 * LoadCursorA (USER32.359)
1713 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1715 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1716 LR_SHARED | LR_DEFAULTSIZE );
1719 /***********************************************************************
1720 * LoadCursorFromFileW (USER32.361)
1722 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1724 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1725 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1728 /***********************************************************************
1729 * LoadCursorFromFileA (USER32.360)
1731 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1733 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1734 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1737 /***********************************************************************
1738 * LoadIconW (USER32.364)
1740 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1742 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1743 LR_SHARED | LR_DEFAULTSIZE );
1746 /***********************************************************************
1747 * LoadIconA (USER32.363)
1749 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1751 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1752 LR_SHARED | LR_DEFAULTSIZE );
1755 /**********************************************************************
1756 * GetIconInfo16 (USER.395)
1758 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1761 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1763 iconinfo->fIcon = ii32.fIcon;
1764 iconinfo->xHotspot = ii32.xHotspot;
1765 iconinfo->yHotspot = ii32.yHotspot;
1766 iconinfo->hbmMask = ii32.hbmMask;
1767 iconinfo->hbmColor = ii32.hbmColor;
1771 /**********************************************************************
1772 * GetIconInfo (USER32.242)
1774 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1775 CURSORICONINFO *ciconinfo;
1777 ciconinfo = GlobalLock16(hIcon);
1781 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1782 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1784 iconinfo->fIcon = TRUE;
1785 iconinfo->xHotspot = 0;
1786 iconinfo->yHotspot = 0;
1790 iconinfo->fIcon = FALSE;
1791 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1792 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1795 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1796 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1797 (char *)(ciconinfo + 1)
1798 + ciconinfo->nHeight *
1799 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1800 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1801 1, 1, (char *)(ciconinfo + 1));
1803 GlobalUnlock16(hIcon);
1808 /**********************************************************************
1809 * CreateIconIndirect (USER32.78)
1811 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1812 BITMAPOBJ *bmpXor,*bmpAnd;
1814 int sizeXor,sizeAnd;
1816 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1817 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1819 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1820 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1822 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1823 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1826 CURSORICONINFO *info;
1828 info = (CURSORICONINFO *)GlobalLock16( hObj );
1830 /* If we are creating an icon, the hotspot is unused */
1831 if (iconinfo->fIcon)
1833 info->ptHotSpot.x = ICON_HOTSPOT;
1834 info->ptHotSpot.y = ICON_HOTSPOT;
1838 info->ptHotSpot.x = iconinfo->xHotspot;
1839 info->ptHotSpot.y = iconinfo->yHotspot;
1842 info->nWidth = bmpXor->bitmap.bmWidth;
1843 info->nHeight = bmpXor->bitmap.bmHeight;
1844 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1845 info->bPlanes = bmpXor->bitmap.bmPlanes;
1846 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1848 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1850 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1851 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1852 GlobalUnlock16( hObj );
1858 /**********************************************************************
1860 DrawIconEx16 (USER.394)
1862 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1863 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1864 HBRUSH16 hbr, UINT16 flags)
1866 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1871 /******************************************************************************
1872 * DrawIconEx [USER32.160] Draws an icon or cursor on device context
1875 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1878 * hdc [I] Handle to device context
1879 * x0 [I] X coordinate of upper left corner
1880 * y0 [I] Y coordinate of upper left corner
1881 * hIcon [I] Handle to icon to draw
1882 * cxWidth [I] Width of icon
1883 * cyWidth [I] Height of icon
1884 * istep [I] Index of frame in animated cursor
1885 * hbr [I] Handle to background brush
1886 * flags [I] Icon-drawing flags
1892 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1893 INT cxWidth, INT cyWidth, UINT istep,
1894 HBRUSH hbr, UINT flags )
1896 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1897 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1898 BOOL result = FALSE, DoOffscreen = FALSE;
1899 HBITMAP hB_off = 0, hOld = 0;
1901 if (!ptr) return FALSE;
1904 FIXME_(icon)("Ignoring istep=%d\n", istep);
1905 if (flags & DI_COMPAT)
1906 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1908 /* Calculate the size of the destination image. */
1911 if (flags & DI_DEFAULTSIZE)
1912 cxWidth = GetSystemMetrics (SM_CXICON);
1914 cxWidth = ptr->nWidth;
1918 if (flags & DI_DEFAULTSIZE)
1919 cyWidth = GetSystemMetrics (SM_CYICON);
1921 cyWidth = ptr->nHeight;
1924 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1925 STOCK_HOLLOW_BRUSH)))
1927 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1930 UINT16 magic = object->wMagic;
1931 GDI_HEAP_UNLOCK(hbr);
1932 DoOffscreen = magic == BRUSH_MAGIC;
1943 hDC_off = CreateCompatibleDC(hdc);
1944 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1945 if (hDC_off && hB_off) {
1946 hOld = SelectObject(hDC_off, hB_off);
1947 FillRect(hDC_off, &r, hbr);
1951 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1953 HBITMAP hXorBits, hAndBits;
1954 COLORREF oldFg, oldBg;
1957 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1959 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1960 ptr->bPlanes, ptr->bBitsPerPixel,
1963 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1964 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1965 1, 1, (char *)(ptr+1) );
1966 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1967 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1969 if (hXorBits && hAndBits)
1971 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1972 if (flags & DI_MASK)
1975 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1976 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1978 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1979 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1981 SelectObject( hMemDC, hXorBits );
1982 if (flags & DI_IMAGE)
1985 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1986 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1988 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1989 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1991 SelectObject( hMemDC, hBitTemp );
1995 SetTextColor( hdc, oldFg );
1996 SetBkColor( hdc, oldBg );
1997 if (hXorBits) DeleteObject( hXorBits );
1998 if (hAndBits) DeleteObject( hAndBits );
1999 SetStretchBltMode (hdc, nStretchMode);
2001 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2002 SelectObject(hDC_off, hOld);
2005 if (hMemDC) DeleteDC( hMemDC );
2006 if (hDC_off) DeleteDC(hDC_off);
2007 if (hB_off) DeleteObject(hB_off);
2008 GlobalUnlock16( hIcon );
2012 /**********************************************************************
2015 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2017 HBITMAP hbitmap = 0;
2022 BITMAPINFO *info, *fix_info=NULL;
2026 if (!(loadflags & LR_LOADFROMFILE)) {
2027 if (!instance) /* OEM bitmap */
2032 if (HIWORD((int)name)) return 0;
2033 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2034 dc = DC_GetDCPtr( hdc );
2035 if(dc->funcs->pLoadOEMResource)
2036 hbitmap = dc->funcs->pLoadOEMResource( LOWORD((int)name),
2038 GDI_HEAP_UNLOCK( hdc );
2043 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2044 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2046 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2050 if (!(ptr = (char *)VIRTUAL_MapFileW( name ))) return 0;
2051 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2053 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2054 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2058 memcpy(fix_info, info, size);
2059 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2060 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2061 if ((hdc = GetDC(0)) != 0) {
2062 char *bits = (char *)info + size;
2063 if (loadflags & LR_CREATEDIBSECTION) {
2065 hbitmap = CreateDIBSection(hdc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2066 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2067 SetDIBits(hdc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2071 hbitmap = CreateDIBitmap( hdc, &fix_info->bmiHeader, CBM_INIT,
2072 bits, fix_info, DIB_RGB_COLORS );
2074 ReleaseDC( 0, hdc );
2079 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2084 /***********************************************************************
2085 * LoadImage16 [USER.389]
2088 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2089 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2091 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2092 return LoadImageA( hinst, nameStr, type,
2093 desiredx, desiredy, loadflags );
2096 /**********************************************************************
2097 * LoadImageA (USER32.365)
2099 * FIXME: implementation lacks some features, see LR_ defines in windows.h
2102 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2103 INT desiredx, INT desiredy, UINT loadflags)
2108 if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
2109 else u_name=(LPWSTR)name;
2110 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2111 if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
2116 /******************************************************************************
2117 * LoadImageW [USER32.366] Loads an icon, cursor, or bitmap
2120 * hinst [I] Handle of instance that contains image
2121 * name [I] Name of image
2122 * type [I] Type of image
2123 * desiredx [I] Desired width
2124 * desiredy [I] Desired height
2125 * loadflags [I] Load flags
2128 * Success: Handle to newly loaded image
2131 * FIXME: Implementation lacks some features, see LR_ defines in windows.h
2133 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2134 INT desiredx, INT desiredy, UINT loadflags )
2137 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2138 hinst,name,type,desiredx,desiredy,loadflags);
2140 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2141 hinst,name,type,desiredx,desiredy,loadflags);
2143 if (loadflags & LR_DEFAULTSIZE) {
2144 if (type == IMAGE_ICON) {
2145 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2146 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2147 } else if (type == IMAGE_CURSOR) {
2148 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2149 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2152 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2155 return BITMAP_Load( hinst, name, loadflags );
2160 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
2165 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2166 palEnts, FALSE, loadflags);
2170 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2171 1, TRUE, loadflags);
2177 /******************************************************************************
2178 * CopyImage16 [USER.390] Creates new image and copies attributes to it
2181 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2182 INT16 desiredy, UINT16 flags )
2184 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2185 (INT)desiredy, (UINT)flags);
2188 /******************************************************************************
2189 * CopyImage [USER32.61] Creates new image and copies attributes to it
2192 * hnd [I] Handle to image to copy
2193 * type [I] Type of image to copy
2194 * desiredx [I] Desired width of new image
2195 * desiredy [I] Desired height of new image
2196 * flags [I] Copy flags
2199 * Success: Handle to newly created image
2202 * FIXME: implementation still lacks nearly all features, see LR_*
2203 * defines in windows.h
2205 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2206 INT desiredy, UINT flags )
2211 return BITMAP_CopyBitmap(hnd);
2213 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2215 /* Should call CURSORICON_ExtCopy but more testing
2216 * needs to be done before we change this
2218 return CopyCursor(hnd);
2224 /******************************************************************************
2225 * LoadBitmapW [USER32.358] Loads bitmap from the executable file
2228 * Success: Handle to specified bitmap
2231 HBITMAP WINAPI LoadBitmapW(
2232 HINSTANCE instance, /* [in] Handle to application instance */
2233 LPCWSTR name) /* [in] Address of bitmap resource name */
2235 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2238 /**********************************************************************
2239 * LoadBitmapA (USER32.357)
2241 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2243 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2246 /**********************************************************************
2247 * LoadBitmap16 (USER.175)
2249 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, SEGPTR name )
2251 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
2252 return LoadBitmapA( instance, nameStr );