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)
58 static HCURSOR hActiveCursor = 0; /* Active cursor */
59 static INT CURSOR_ShowCount = 0; /* Cursor display count */
60 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
63 /**********************************************************************
64 * ICONCACHE for cursors/icons loaded with LR_SHARED.
66 * FIXME: This should not be allocated on the system heap, but on a
67 * subsystem-global heap (i.e. one for all Win16 processes,
68 * and one each for every Win32 process).
70 typedef struct tagICONCACHE
72 struct tagICONCACHE *next;
83 static ICONCACHE *IconAnchor = NULL;
84 static CRITICAL_SECTION IconCrst;
85 static DWORD ICON_HOTSPOT = 0x42424242;
87 /**********************************************************************
90 void CURSORICON_Init( void )
92 InitializeCriticalSection( &IconCrst );
93 MakeCriticalSectionGlobal( &IconCrst );
96 /**********************************************************************
97 * CURSORICON_FindSharedIcon
99 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
104 EnterCriticalSection( &IconCrst );
106 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
107 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
110 handle = ptr->handle;
114 LeaveCriticalSection( &IconCrst );
119 /*************************************************************************
120 * CURSORICON_FindCache
122 * Given a handle, find the coresponding cache element
125 * Handle [I] handle to an Image
128 * Success: The cache entry
132 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
135 ICONCACHE *pRet=NULL;
136 BOOL IsFound = FALSE;
139 EnterCriticalSection( &IconCrst );
141 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
143 if ( handle == ptr->handle )
150 LeaveCriticalSection( &IconCrst );
155 /**********************************************************************
156 * CURSORICON_AddSharedIcon
158 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
160 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
163 ptr->hModule = hModule;
165 ptr->handle = handle;
166 ptr->hGroupRsrc = hGroupRsrc;
169 EnterCriticalSection( &IconCrst );
170 ptr->next = IconAnchor;
172 LeaveCriticalSection( &IconCrst );
175 /**********************************************************************
176 * CURSORICON_DelSharedIcon
178 static INT CURSORICON_DelSharedIcon( HANDLE handle )
183 EnterCriticalSection( &IconCrst );
185 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
186 if ( ptr->handle == handle )
188 if ( ptr->count > 0 ) ptr->count--;
193 LeaveCriticalSection( &IconCrst );
198 /**********************************************************************
199 * CURSORICON_FreeModuleIcons
201 void CURSORICON_FreeModuleIcons( HMODULE hModule )
203 ICONCACHE **ptr = &IconAnchor;
205 if ( HIWORD( hModule ) )
206 hModule = MapHModuleLS( hModule );
208 hModule = GetExePtr( hModule );
210 EnterCriticalSection( &IconCrst );
214 if ( (*ptr)->hModule == hModule )
216 ICONCACHE *freePtr = *ptr;
217 *ptr = freePtr->next;
219 GlobalFree16( freePtr->handle );
220 HeapFree( SystemHeap, 0, freePtr );
226 LeaveCriticalSection( &IconCrst );
229 /**********************************************************************
230 * CURSORICON_FindBestIcon
232 * Find the icon closest to the requested size and number of colors.
234 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
235 int height, int colors )
238 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
239 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
240 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
242 if (dir->idCount < 1)
244 WARN_(icon)("Empty directory!\n" );
247 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
250 iTotalDiff = 0xFFFFFFFF;
251 iColorDiff = 0xFFFFFFFF;
252 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
254 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
255 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
257 if(iTotalDiff > (iTempXDiff + iTempYDiff))
261 iTotalDiff = iXDiff + iYDiff;
265 /* Find Best Colors for Best Fit */
266 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
268 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
269 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
271 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
272 if(iColorDiff > iTempColorDiff)
275 iColorDiff = iTempColorDiff;
284 /**********************************************************************
285 * CURSORICON_FindBestCursor
287 * Find the cursor closest to the requested size.
288 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
291 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
292 int width, int height, int color)
294 int i, maxwidth, maxheight;
295 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
297 if (dir->idCount < 1)
299 WARN_(cursor)("Empty directory!\n" );
302 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
304 /* Double height to account for AND and XOR masks */
308 /* First find the largest one smaller than or equal to the requested size*/
310 maxwidth = maxheight = 0;
311 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
312 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
313 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
314 (entry->wBitCount == 1))
317 maxwidth = entry->ResInfo.cursor.wWidth;
318 maxheight = entry->ResInfo.cursor.wHeight;
320 if (bestEntry) return bestEntry;
322 /* Now find the smallest one larger than the requested size */
324 maxwidth = maxheight = 255;
325 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
326 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
327 (entry->wBitCount == 1))
330 maxwidth = entry->ResInfo.cursor.wWidth;
331 maxheight = entry->ResInfo.cursor.wHeight;
337 /*********************************************************************
338 * The main purpose of this function is to create fake resource directory
339 * and fake resource entries. There are several reasons for this:
340 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
342 * There are some "bad" cursor files which do not have
343 * bColorCount initialized but instead one must read this info
344 * directly from corresponding DIB sections
345 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
347 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
348 CURSORICONDIR **res, LPBYTE **ptr)
351 CURSORICONFILEDIR *bits;
352 int entries, size, i;
356 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
358 /* FIXME: test for inimated icons
359 * hack to load the first icon from the *.ani file
361 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
362 { LPBYTE pos = (LPBYTE) bits;
363 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
366 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
367 { FIXME_(cursor)("icon entry found! %p\n", bits);
369 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
372 bits=(CURSORICONFILEDIR*)(pos+4);
373 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
377 if (pos>=(LPBYTE)bits+766) goto fail;
380 if (!(entries = bits->idCount)) goto fail;
381 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
382 _free = (LPBYTE) size;
384 for (i=0; i < entries; i++)
385 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
387 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
388 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
389 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
391 _free = (LPBYTE)(*res) + (int)_free;
392 memcpy((*res), bits, 6);
393 for (i=0; i<entries; i++)
395 ((LPBYTE*)(*ptr))[i] = _free;
397 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
398 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
399 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
400 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
401 _free+=sizeof(POINT16);
403 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
404 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
405 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
407 (*res)->idEntries[i].wPlanes=1;
408 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
409 bits->idEntries[i].dwDIBOffset))->biBitCount;
410 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
411 (*res)->idEntries[i].wResId=i+1;
413 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
414 (*res)->idEntries[i].dwBytesInRes);
415 _free += (*res)->idEntries[i].dwBytesInRes;
417 UnmapViewOfFile( bits );
420 if (*res) HeapFree( GetProcessHeap(), 0, *res );
421 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
422 UnmapViewOfFile( bits );
427 /**********************************************************************
428 * CURSORICON_CreateFromResource
430 * Create a cursor or icon from in-memory resource template.
432 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
433 * with cbSize parameter as well.
435 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
436 UINT cbSize, BOOL bIcon, DWORD dwVersion,
437 INT width, INT height, UINT loadflags )
439 int sizeAnd, sizeXor;
440 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
441 BITMAPOBJ *bmpXor, *bmpAnd;
448 hotspot.x = ICON_HOTSPOT;
449 hotspot.y = ICON_HOTSPOT;
451 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
452 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
453 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
454 if (dwVersion == 0x00020000)
456 FIXME_(cursor)("\t2.xx resources are not supported\n");
461 bmi = (BITMAPINFO *)bits;
462 else /* get the hotspot */
464 POINT16 *pt = (POINT16 *)bits;
466 bmi = (BITMAPINFO *)(pt + 1);
468 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
470 if (!width) width = bmi->bmiHeader.biWidth;
471 if (!height) height = bmi->bmiHeader.biHeight/2;
472 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
473 (bmi->bmiHeader.biWidth != width);
475 /* Check bitmap header */
477 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
478 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
479 bmi->bmiHeader.biCompression != BI_RGB) )
481 WARN_(cursor)("\tinvalid resource bitmap header.\n");
485 if( (hdc = GetDC( 0 )) )
489 /* Make sure we have room for the monochrome bitmap later on.
490 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
491 * up to and including the biBitCount. In-memory icon resource
492 * format is as follows:
494 * BITMAPINFOHEADER icHeader // DIB header
495 * RGBQUAD icColors[] // Color table
496 * BYTE icXOR[] // DIB bits for XOR mask
497 * BYTE icAND[] // DIB bits for AND mask
500 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
501 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
503 memcpy( pInfo, bmi, size );
504 pInfo->bmiHeader.biHeight /= 2;
506 /* Create the XOR bitmap */
511 hXorBits = CreateCompatibleBitmap(hdc, width, height);
515 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
520 HDC hMem = CreateCompatibleDC(hdc);
524 hOld = SelectObject(hMem, hXorBits);
525 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
526 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
527 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
528 SelectObject(hMem, hOld);
531 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
533 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
534 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
537 char* bits = (char *)bmi + size +
538 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
539 bmi->bmiHeader.biHeight,
540 bmi->bmiHeader.biBitCount) / 2;
542 pInfo->bmiHeader.biBitCount = 1;
543 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
545 RGBQUAD *rgb = pInfo->bmiColors;
547 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
548 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
549 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
550 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
554 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
556 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
557 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
560 /* Create the AND bitmap */
563 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
565 HDC hMem = CreateCompatibleDC(hdc);
569 hOld = SelectObject(hMem, hAndBits);
570 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
571 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
572 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
573 SelectObject(hMem, hOld);
576 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
578 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
579 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
581 if( !hAndBits ) DeleteObject( hXorBits );
583 HeapFree( GetProcessHeap(), 0, pInfo );
588 if( !hXorBits || !hAndBits )
590 WARN_(cursor)("\tunable to create an icon bitmap.\n");
594 /* Now create the CURSORICONINFO structure */
595 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
596 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
597 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
598 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
600 if (hObj) hObj = GlobalReAlloc16( hObj,
601 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
602 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
603 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
606 CURSORICONINFO *info;
608 /* Make it owned by the module */
609 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
611 info = (CURSORICONINFO *)GlobalLock16( hObj );
612 info->ptHotSpot.x = hotspot.x;
613 info->ptHotSpot.y = hotspot.y;
614 info->nWidth = bmpXor->bitmap.bmWidth;
615 info->nHeight = bmpXor->bitmap.bmHeight;
616 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
617 info->bPlanes = bmpXor->bitmap.bmPlanes;
618 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
620 /* Transfer the bitmap bits to the CURSORICONINFO structure */
622 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
623 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
624 GlobalUnlock16( hObj );
627 DeleteObject( hXorBits );
628 DeleteObject( hAndBits );
633 /**********************************************************************
634 * CreateIconFromResourceEx16 (USER.450)
636 * FIXME: not sure about exact parameter types
638 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
639 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
641 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
642 width, height, cFlag);
646 /**********************************************************************
647 * CreateIconFromResource (USER32.76)
649 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
650 BOOL bIcon, DWORD dwVersion)
652 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
656 /**********************************************************************
657 * CreateIconFromResourceEx32 (USER32.77)
659 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
660 BOOL bIcon, DWORD dwVersion,
661 INT width, INT height,
664 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
666 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
667 width, height, cFlag );
671 /**********************************************************************
674 * Load a cursor or icon from resource or file.
676 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
677 INT width, INT height, INT colors,
678 BOOL fCursor, UINT loadflags )
680 HANDLE handle = 0, h = 0;
683 CURSORICONDIRENTRY *dirEntry;
686 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
689 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
692 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
694 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
695 bits = ptr[dirEntry->wResId-1];
696 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
697 !fCursor, 0x00030000, width, height, loadflags);
698 HeapFree( GetProcessHeap(), 0, dir );
699 HeapFree( GetProcessHeap(), 0, ptr );
702 else if ( !hInstance ) /* Load OEM cursor/icon */
709 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
710 if( ansi[0]=='#') /*Check for '#xxx' name */
712 resid = atoi(ansi+1);
713 HeapFree( GetProcessHeap(), 0, ansi );
717 HeapFree( GetProcessHeap(), 0, ansi );
721 else resid = LOWORD(name);
722 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
724 DC *dc = DC_GetDCPtr( hdc );
725 if (dc->funcs->pLoadOEMResource)
726 h = dc->funcs->pLoadOEMResource( resid, fCursor ? OEM_CURSOR : OEM_ICON );
727 GDI_HEAP_UNLOCK( hdc );
732 else /* Load from resource */
738 /* Normalize hInstance (must be uniquely represented for icon cache) */
740 if ( HIWORD( hInstance ) )
741 hInstance = MapHModuleLS( hInstance );
743 hInstance = GetExePtr( hInstance );
745 /* Get directory resource ID */
747 if (!(hRsrc = FindResourceW( hInstance, name,
748 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
751 /* If shared icon, check whether it was already loaded */
753 if ( (loadflags & LR_SHARED)
754 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
757 /* Find the best entry in the directory */
759 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
760 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
762 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
765 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
766 width, height, colors );
767 if (!dirEntry) return 0;
768 wResId = dirEntry->wResId;
769 dwBytesInRes = dirEntry->dwBytesInRes;
770 FreeResource( handle );
772 /* Load the resource */
774 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
775 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
776 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
777 bits = (LPBYTE)LockResource( handle );
778 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
779 !fCursor, 0x00030000, width, height, loadflags);
780 FreeResource( handle );
782 /* If shared icon, add to icon cache */
784 if ( h && (loadflags & LR_SHARED) )
785 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
791 /***********************************************************************
794 * Make a copy of a cursor or icon.
796 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
798 char *ptrOld, *ptrNew;
802 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
803 if (!(hInstance = GetExePtr( hInstance ))) return 0;
804 size = GlobalSize16( handle );
805 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
806 FarSetOwner16( hNew, hInstance );
807 ptrNew = (char *)GlobalLock16( hNew );
808 memcpy( ptrNew, ptrOld, size );
809 GlobalUnlock16( handle );
810 GlobalUnlock16( hNew );
814 /*************************************************************************
817 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
820 * Handle [I] handle to an Image
821 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
822 * iDesiredCX [I] The Desired width of the Image
823 * iDesiredCY [I] The desired height of the Image
824 * nFlags [I] The flags from CopyImage
827 * Success: The new handle of the Image
830 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
831 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
832 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
837 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
838 INT iDesiredCX, INT iDesiredCY,
843 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
844 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
851 /* Best Fit or Monochrome */
852 if( (nFlags & LR_COPYFROMRESOURCE
853 && (iDesiredCX > 0 || iDesiredCY > 0))
854 || nFlags & LR_MONOCHROME)
856 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
858 /* Not Found in Cache, then do a strait copy
860 if(pIconCache == NULL)
862 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
863 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
864 if(nFlags & LR_COPYFROMRESOURCE)
866 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
871 int iTargetCX, iTargetCY;
878 CURSORICONDIRENTRY *pDirEntry;
879 BOOL bIsIcon = (nType == IMAGE_ICON);
881 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
883 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
884 || (iDesiredCX == 0 && iDesiredCY == 0))
886 iDesiredCY = GetSystemMetrics(bIsIcon ?
887 SM_CYICON : SM_CYCURSOR);
888 iDesiredCX = GetSystemMetrics(bIsIcon ?
889 SM_CXICON : SM_CXCURSOR);
892 /* Retreive the CURSORICONDIRENTRY
894 if (!(hMem = LoadResource( pIconCache->hModule ,
895 pIconCache->hGroupRsrc)))
899 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
908 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
909 pDir, iDesiredCX, iDesiredCY, 256);
913 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
914 pDir, iDesiredCX, iDesiredCY, 1);
917 wResId = pDirEntry->wResId;
918 dwBytesInRes = pDirEntry->dwBytesInRes;
921 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
922 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
923 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
927 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
928 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
932 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
937 pBits = (LPBYTE)LockResource( hMem );
939 iTargetCY = GetSystemMetrics(SM_CYICON);
940 iTargetCX = GetSystemMetrics(SM_CXICON);
942 /* Create a New Icon with the proper dimension
944 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
945 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
951 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
952 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
957 /***********************************************************************
958 * CURSORICON_IconToCursor
960 * Converts bitmap to mono and truncates if icon is too large (should
961 * probably do StretchBlt() instead).
963 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
966 CURSORICONINFO *pIcon = NULL;
967 HTASK16 hTask = GetCurrentTask();
968 TDB* pTask = (TDB *)GlobalLock16(hTask);
971 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
972 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
974 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
977 pIcon = GlobalLock16(hRet);
979 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
987 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
988 BYTE* psPtr, *pxbPtr = pXorBits;
989 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
994 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
995 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
997 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
998 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
999 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
1001 memset(pXorBits, 0, 128);
1002 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
1003 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
1004 cI.nWidth = 32; cI.nHeight = 32;
1005 cI.nWidthBytes = 4; /* 32x1bpp */
1007 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
1008 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
1010 for( iy = 0; iy < maxy; iy++ )
1012 unsigned shift = iy % 2;
1014 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
1015 (and_width > 4) ? 4 : and_width );
1016 for( ix = 0; ix < maxx; ix++ )
1018 if( bSemiTransparent && ((ix+shift)%2) )
1020 /* set AND bit, XOR bit stays 0 */
1022 pbc = pAndBits + iy * 4 + ix/8;
1023 *pbc |= 0x80 >> (ix%8);
1027 /* keep AND bit, set XOR bit */
1029 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1030 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1031 if(!PALETTE_Driver->pIsDark(val))
1033 pbc = pxbPtr + ix/8;
1034 *pbc |= 0x80 >> (ix%8);
1042 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
1044 if( !hRet ) /* fall back on default drag cursor */
1045 hRet = CURSORICON_Copy( pTask->hInstance ,
1046 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1047 GetSystemMetrics(SM_CXCURSOR),
1048 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1055 /***********************************************************************
1056 * LoadCursor16 (USER.173)
1058 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
1060 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1061 return LoadCursorA( hInstance, nameStr );
1065 /***********************************************************************
1066 * LoadIcon16 (USER.174)
1068 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
1070 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1071 return LoadIconA( hInstance, nameStr );
1075 /***********************************************************************
1076 * CreateCursor16 (USER.406)
1078 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1079 INT16 xHotSpot, INT16 yHotSpot,
1080 INT16 nWidth, INT16 nHeight,
1081 LPCVOID lpANDbits, LPCVOID lpXORbits )
1083 CURSORICONINFO info;
1085 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1086 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1088 info.ptHotSpot.x = xHotSpot;
1089 info.ptHotSpot.y = yHotSpot;
1090 info.nWidth = nWidth;
1091 info.nHeight = nHeight;
1092 info.nWidthBytes = 0;
1094 info.bBitsPerPixel = 1;
1096 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1100 /***********************************************************************
1101 * CreateCursor32 (USER32.67)
1103 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1104 INT xHotSpot, INT yHotSpot,
1105 INT nWidth, INT nHeight,
1106 LPCVOID lpANDbits, LPCVOID lpXORbits )
1108 CURSORICONINFO info;
1110 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1111 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1113 info.ptHotSpot.x = xHotSpot;
1114 info.ptHotSpot.y = yHotSpot;
1115 info.nWidth = nWidth;
1116 info.nHeight = nHeight;
1117 info.nWidthBytes = 0;
1119 info.bBitsPerPixel = 1;
1121 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1125 /***********************************************************************
1126 * CreateIcon16 (USER.407)
1128 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1129 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1130 LPCVOID lpANDbits, LPCVOID lpXORbits )
1132 CURSORICONINFO info;
1134 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1135 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1137 info.ptHotSpot.x = ICON_HOTSPOT;
1138 info.ptHotSpot.y = ICON_HOTSPOT;
1139 info.nWidth = nWidth;
1140 info.nHeight = nHeight;
1141 info.nWidthBytes = 0;
1142 info.bPlanes = bPlanes;
1143 info.bBitsPerPixel = bBitsPixel;
1145 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1149 /***********************************************************************
1150 * CreateIcon32 (USER32.75)
1152 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1153 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
1154 LPCVOID lpANDbits, LPCVOID lpXORbits )
1156 CURSORICONINFO info;
1158 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1159 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1161 info.ptHotSpot.x = ICON_HOTSPOT;
1162 info.ptHotSpot.y = ICON_HOTSPOT;
1163 info.nWidth = nWidth;
1164 info.nHeight = nHeight;
1165 info.nWidthBytes = 0;
1166 info.bPlanes = bPlanes;
1167 info.bBitsPerPixel = bBitsPixel;
1169 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1173 /***********************************************************************
1174 * CreateCursorIconIndirect (USER.408)
1176 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1177 CURSORICONINFO *info,
1183 int sizeAnd, sizeXor;
1185 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1186 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1187 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1188 sizeXor = info->nHeight * info->nWidthBytes;
1189 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1190 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1191 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1193 if (hInstance) FarSetOwner16( handle, hInstance );
1194 ptr = (char *)GlobalLock16( handle );
1195 memcpy( ptr, info, sizeof(*info) );
1196 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1197 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1198 GlobalUnlock16( handle );
1203 /***********************************************************************
1204 * CopyIcon16 (USER.368)
1206 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1208 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1209 return CURSORICON_Copy( hInstance, hIcon );
1213 /***********************************************************************
1214 * CopyIcon32 (USER32.60)
1216 HICON WINAPI CopyIcon( HICON hIcon )
1218 HTASK16 hTask = GetCurrentTask ();
1219 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1220 TRACE_(icon)("%04x\n", hIcon );
1221 return CURSORICON_Copy( pTask->hInstance, hIcon );
1225 /***********************************************************************
1226 * CopyCursor16 (USER.369)
1228 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1230 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1231 return CURSORICON_Copy( hInstance, hCursor );
1234 /**********************************************************************
1235 * CURSORICON_Destroy (USER.610)
1237 * This routine is actually exported from Win95 USER under the name
1238 * DestroyIcon32 ... The behaviour implemented here should mimic
1239 * the Win95 one exactly, especially the return values, which
1240 * depend on the setting of various flags.
1242 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1246 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1248 /* Check whether destroying active cursor */
1250 if ( hActiveCursor == handle )
1252 ERR_(cursor)("Destroying active cursor!\n" );
1256 /* Try shared cursor/icon first */
1258 if ( !(flags & CID_NONSHARED) )
1260 INT count = CURSORICON_DelSharedIcon( handle );
1263 return (flags & CID_WIN32)? TRUE : (count == 0);
1265 /* FIXME: OEM cursors/icons should be recognized */
1268 /* Now assume non-shared cursor/icon */
1270 retv = GlobalFree16( handle );
1271 return (flags & CID_RESOURCE)? retv : TRUE;
1274 /***********************************************************************
1275 * DestroyIcon16 (USER.457)
1277 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1279 return CURSORICON_Destroy( hIcon, 0 );
1282 /***********************************************************************
1283 * DestroyIcon (USER32.133)
1285 BOOL WINAPI DestroyIcon( HICON hIcon )
1287 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1290 /***********************************************************************
1291 * DestroyCursor16 (USER.458)
1293 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1295 return CURSORICON_Destroy( hCursor, 0 );
1298 /***********************************************************************
1299 * DestroyCursor (USER32.132)
1301 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1303 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1307 /***********************************************************************
1308 * DrawIcon16 (USER.84)
1310 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1312 return DrawIcon( hdc, x, y, hIcon );
1316 /***********************************************************************
1317 * DrawIcon32 (USER32.159)
1319 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1321 CURSORICONINFO *ptr;
1323 HBITMAP hXorBits, hAndBits;
1324 COLORREF oldFg, oldBg;
1326 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1327 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1328 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1330 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1331 ptr->bBitsPerPixel, (char *)(ptr + 1)
1332 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1333 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1334 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1336 if (hXorBits && hAndBits)
1338 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1339 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1340 SelectObject( hMemDC, hXorBits );
1341 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1342 SelectObject( hMemDC, hBitTemp );
1345 if (hXorBits) DeleteObject( hXorBits );
1346 if (hAndBits) DeleteObject( hAndBits );
1347 GlobalUnlock16( hIcon );
1348 SetTextColor( hdc, oldFg );
1349 SetBkColor( hdc, oldBg );
1354 /***********************************************************************
1355 * DumpIcon (USER.459)
1357 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1358 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1360 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1361 int sizeAnd, sizeXor;
1363 if (!info) return 0;
1364 sizeXor = info->nHeight * info->nWidthBytes;
1365 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1366 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1367 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1368 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1369 return MAKELONG( sizeXor, sizeXor );
1373 /***********************************************************************
1374 * SetCursor16 (USER.69)
1376 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1378 return (HCURSOR16)SetCursor( hCursor );
1382 /***********************************************************************
1383 * SetCursor32 (USER32.472)
1385 * A handle to the previous cursor shape.
1387 HCURSOR WINAPI SetCursor(
1388 HCURSOR hCursor /* Handle of cursor to show */
1392 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1393 TRACE_(cursor)("%04x\n", hCursor );
1394 hOldCursor = hActiveCursor;
1395 hActiveCursor = hCursor;
1396 /* Change the cursor shape only if it is visible */
1397 if (CURSOR_ShowCount >= 0)
1399 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1400 GlobalUnlock16( hActiveCursor );
1406 /***********************************************************************
1407 * SetCursorPos16 (USER.70)
1409 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1411 SetCursorPos( x, y );
1415 /***********************************************************************
1416 * SetCursorPos32 (USER32.474)
1418 BOOL WINAPI SetCursorPos( INT x, INT y )
1420 DISPLAY_MoveCursor( x, y );
1425 /***********************************************************************
1426 * ShowCursor16 (USER.71)
1428 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1430 return ShowCursor( bShow );
1434 /***********************************************************************
1435 * ShowCursor32 (USER32.530)
1437 INT WINAPI ShowCursor( BOOL bShow )
1439 TRACE_(cursor)("%d, count=%d\n",
1440 bShow, CURSOR_ShowCount );
1444 if (++CURSOR_ShowCount == 0) /* Show it */
1446 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1447 GlobalUnlock16( hActiveCursor );
1452 if (--CURSOR_ShowCount == -1) /* Hide it */
1453 DISPLAY_SetCursor( NULL );
1455 return CURSOR_ShowCount;
1459 /***********************************************************************
1460 * GetCursor16 (USER.247)
1462 HCURSOR16 WINAPI GetCursor16(void)
1464 return hActiveCursor;
1468 /***********************************************************************
1469 * GetCursor32 (USER32.227)
1471 HCURSOR WINAPI GetCursor(void)
1473 return hActiveCursor;
1477 /***********************************************************************
1478 * ClipCursor16 (USER.16)
1480 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1482 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1483 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1488 /***********************************************************************
1489 * ClipCursor32 (USER32.53)
1491 BOOL WINAPI ClipCursor( const RECT *rect )
1493 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1494 else CopyRect( &CURSOR_ClipRect, rect );
1499 /***********************************************************************
1500 * GetCursorPos16 (USER.17)
1502 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1509 TRACE_(cursor)("ret=%d,%d\n", pt->x, pt->y );
1514 /***********************************************************************
1515 * GetCursorPos32 (USER32.229)
1517 BOOL WINAPI GetCursorPos( POINT *pt )
1522 ret = GetCursorPos16( &pt16 );
1523 if (pt) CONV_POINT16TO32( &pt16, pt );
1524 return ((pt) ? ret : 0);
1528 /***********************************************************************
1529 * GetClipCursor16 (USER.309)
1531 void WINAPI GetClipCursor16( RECT16 *rect )
1533 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1537 /***********************************************************************
1538 * GetClipCursor32 (USER32.221)
1540 BOOL WINAPI GetClipCursor( RECT *rect )
1544 CopyRect( rect, &CURSOR_ClipRect );
1550 /**********************************************************************
1551 * LookupIconIdFromDirectoryEx16 (USER.364)
1553 * FIXME: exact parameter sizes
1555 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1556 INT16 width, INT16 height, UINT16 cFlag )
1558 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1560 if( dir && !dir->idReserved && (dir->idType & 3) )
1562 CURSORICONDIRENTRY* entry;
1567 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1570 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1575 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1577 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1579 if( entry ) retVal = entry->wResId;
1581 else WARN_(cursor)("invalid resource directory\n");
1585 /**********************************************************************
1586 * LookupIconIdFromDirectoryEx32 (USER32.380)
1588 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1589 INT width, INT height, UINT cFlag )
1591 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1594 /**********************************************************************
1595 * LookupIconIdFromDirectory (USER.???)
1597 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1599 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1600 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1601 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1604 /**********************************************************************
1605 * LookupIconIdFromDirectory (USER32.379)
1607 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1609 return LookupIconIdFromDirectoryEx( dir, bIcon,
1610 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1611 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1614 /**********************************************************************
1615 * GetIconID (USER.455)
1617 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1619 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1621 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1622 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1627 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1628 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1630 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1631 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1633 WARN_(cursor)("invalid res type %ld\n", resType );
1638 /**********************************************************************
1639 * LoadCursorIconHandler (USER.336)
1641 * Supposed to load resources of Windows 2.x applications.
1643 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1645 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1646 hResource, hModule, hRsrc);
1647 return (HGLOBAL16)0;
1650 /**********************************************************************
1651 * LoadDIBIconHandler (USER.357)
1653 * RT_ICON resource loader, installed by USER_SignalProc when module
1656 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1658 /* If hResource is zero we must allocate a new memory block, if it's
1659 * non-zero but GlobalLock() returns NULL then it was discarded and
1660 * we have to recommit some memory, otherwise we just need to check
1661 * the block size. See LoadProc() in 16-bit SDK for more.
1664 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1667 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1668 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1669 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1670 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1675 /**********************************************************************
1676 * LoadDIBCursorHandler (USER.356)
1678 * RT_CURSOR resource loader. Same as above.
1680 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1682 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1685 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1686 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1687 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1688 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1693 /**********************************************************************
1694 * LoadIconHandler (USER.456)
1696 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1698 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1700 TRACE_(cursor)("hRes=%04x\n",hResource);
1702 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1703 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1706 /***********************************************************************
1707 * LoadCursorW (USER32.362)
1709 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1711 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1712 LR_SHARED | LR_DEFAULTSIZE );
1715 /***********************************************************************
1716 * LoadCursorA (USER32.359)
1718 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1720 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1721 LR_SHARED | LR_DEFAULTSIZE );
1724 /***********************************************************************
1725 * LoadCursorFromFileW (USER32.361)
1727 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1729 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1730 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1733 /***********************************************************************
1734 * LoadCursorFromFileA (USER32.360)
1736 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1738 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1739 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1742 /***********************************************************************
1743 * LoadIconW (USER32.364)
1745 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1747 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1748 LR_SHARED | LR_DEFAULTSIZE );
1751 /***********************************************************************
1752 * LoadIconA (USER32.363)
1754 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1756 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1757 LR_SHARED | LR_DEFAULTSIZE );
1760 /**********************************************************************
1761 * GetIconInfo16 (USER.395)
1763 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1766 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1768 iconinfo->fIcon = ii32.fIcon;
1769 iconinfo->xHotspot = ii32.xHotspot;
1770 iconinfo->yHotspot = ii32.yHotspot;
1771 iconinfo->hbmMask = ii32.hbmMask;
1772 iconinfo->hbmColor = ii32.hbmColor;
1776 /**********************************************************************
1777 * GetIconInfo32 (USER32.242)
1779 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1780 CURSORICONINFO *ciconinfo;
1782 ciconinfo = GlobalLock16(hIcon);
1786 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1787 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1789 iconinfo->fIcon = TRUE;
1790 iconinfo->xHotspot = 0;
1791 iconinfo->yHotspot = 0;
1795 iconinfo->fIcon = FALSE;
1796 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1797 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1800 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1801 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1802 (char *)(ciconinfo + 1)
1803 + ciconinfo->nHeight *
1804 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1805 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1806 1, 1, (char *)(ciconinfo + 1));
1808 GlobalUnlock16(hIcon);
1813 /**********************************************************************
1814 * CreateIconIndirect (USER32.78)
1816 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1817 BITMAPOBJ *bmpXor,*bmpAnd;
1819 int sizeXor,sizeAnd;
1821 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1822 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1824 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1825 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1827 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1828 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1831 CURSORICONINFO *info;
1833 info = (CURSORICONINFO *)GlobalLock16( hObj );
1835 /* If we are creating an icon, the hotspot is unused */
1836 if (iconinfo->fIcon)
1838 info->ptHotSpot.x = ICON_HOTSPOT;
1839 info->ptHotSpot.y = ICON_HOTSPOT;
1843 info->ptHotSpot.x = iconinfo->xHotspot;
1844 info->ptHotSpot.y = iconinfo->yHotspot;
1847 info->nWidth = bmpXor->bitmap.bmWidth;
1848 info->nHeight = bmpXor->bitmap.bmHeight;
1849 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1850 info->bPlanes = bmpXor->bitmap.bmPlanes;
1851 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1853 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1855 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1856 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1857 GlobalUnlock16( hObj );
1863 /**********************************************************************
1865 DrawIconEx16 (USER.394)
1867 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1868 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1869 HBRUSH16 hbr, UINT16 flags)
1871 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1876 /******************************************************************************
1877 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1880 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1883 * hdc [I] Handle to device context
1884 * x0 [I] X coordinate of upper left corner
1885 * y0 [I] Y coordinate of upper left corner
1886 * hIcon [I] Handle to icon to draw
1887 * cxWidth [I] Width of icon
1888 * cyWidth [I] Height of icon
1889 * istep [I] Index of frame in animated cursor
1890 * hbr [I] Handle to background brush
1891 * flags [I] Icon-drawing flags
1897 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1898 INT cxWidth, INT cyWidth, UINT istep,
1899 HBRUSH hbr, UINT flags )
1901 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1902 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1903 BOOL result = FALSE, DoOffscreen = FALSE;
1904 HBITMAP hB_off = 0, hOld = 0;
1906 if (!ptr) return FALSE;
1909 FIXME_(icon)("Ignoring istep=%d\n", istep);
1910 if (flags & DI_COMPAT)
1911 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1913 /* Calculate the size of the destination image. */
1916 if (flags & DI_DEFAULTSIZE)
1917 cxWidth = GetSystemMetrics (SM_CXICON);
1919 cxWidth = ptr->nWidth;
1923 if (flags & DI_DEFAULTSIZE)
1924 cyWidth = GetSystemMetrics (SM_CYICON);
1926 cyWidth = ptr->nHeight;
1929 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1930 STOCK_HOLLOW_BRUSH)))
1932 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1935 UINT16 magic = object->wMagic;
1936 GDI_HEAP_UNLOCK(hbr);
1937 DoOffscreen = magic == BRUSH_MAGIC;
1948 hDC_off = CreateCompatibleDC(hdc);
1949 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1950 if (hDC_off && hB_off) {
1951 hOld = SelectObject(hDC_off, hB_off);
1952 FillRect(hDC_off, &r, hbr);
1956 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1958 HBITMAP hXorBits, hAndBits;
1959 COLORREF oldFg, oldBg;
1962 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1964 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1965 ptr->bPlanes, ptr->bBitsPerPixel,
1968 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1969 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1970 1, 1, (char *)(ptr+1) );
1971 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1972 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1974 if (hXorBits && hAndBits)
1976 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1977 if (flags & DI_MASK)
1980 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1981 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1983 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1984 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1986 SelectObject( hMemDC, hXorBits );
1987 if (flags & DI_IMAGE)
1990 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1991 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1993 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1994 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1996 SelectObject( hMemDC, hBitTemp );
2000 SetTextColor( hdc, oldFg );
2001 SetBkColor( hdc, oldBg );
2002 if (hXorBits) DeleteObject( hXorBits );
2003 if (hAndBits) DeleteObject( hAndBits );
2004 SetStretchBltMode (hdc, nStretchMode);
2006 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2007 SelectObject(hDC_off, hOld);
2010 if (hMemDC) DeleteDC( hMemDC );
2011 if (hDC_off) DeleteDC(hDC_off);
2012 if (hB_off) DeleteObject(hB_off);
2013 GlobalUnlock16( hIcon );