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 iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
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 if(nFlags & LR_DEFAULTSIZE)
941 iTargetCY = GetSystemMetrics(SM_CYICON);
942 iTargetCX = GetSystemMetrics(SM_CXICON);
945 /* Create a New Icon with the proper dimension
947 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
948 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
954 TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
955 hNew = CURSORICON_Copy(pTask->hInstance, Handle);
960 /***********************************************************************
961 * CURSORICON_IconToCursor
963 * Converts bitmap to mono and truncates if icon is too large (should
964 * probably do StretchBlt() instead).
966 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
969 CURSORICONINFO *pIcon = NULL;
970 HTASK16 hTask = GetCurrentTask();
971 TDB* pTask = (TDB *)GlobalLock16(hTask);
974 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
975 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
977 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
980 pIcon = GlobalLock16(hRet);
982 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
984 GlobalUnlock16(hRet);
990 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
991 BYTE* psPtr, *pxbPtr = pXorBits;
992 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
997 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
998 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
1000 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
1001 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
1002 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
1004 memset(pXorBits, 0, 128);
1005 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
1006 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
1007 cI.nWidth = 32; cI.nHeight = 32;
1008 cI.nWidthBytes = 4; /* 32x1bpp */
1010 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
1011 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
1013 for( iy = 0; iy < maxy; iy++ )
1015 unsigned shift = iy % 2;
1017 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
1018 (and_width > 4) ? 4 : and_width );
1019 for( ix = 0; ix < maxx; ix++ )
1021 if( bSemiTransparent && ((ix+shift)%2) )
1023 /* set AND bit, XOR bit stays 0 */
1025 pbc = pAndBits + iy * 4 + ix/8;
1026 *pbc |= 0x80 >> (ix%8);
1030 /* keep AND bit, set XOR bit */
1032 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1033 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1034 if(!PALETTE_Driver->pIsDark(val))
1036 pbc = pxbPtr + ix/8;
1037 *pbc |= 0x80 >> (ix%8);
1045 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
1047 if( !hRet ) /* fall back on default drag cursor */
1048 hRet = CURSORICON_Copy( pTask->hInstance ,
1049 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1050 GetSystemMetrics(SM_CXCURSOR),
1051 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1058 /***********************************************************************
1059 * LoadCursor16 (USER.173)
1061 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
1063 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1064 return LoadCursorA( hInstance, nameStr );
1068 /***********************************************************************
1069 * LoadIcon16 (USER.174)
1071 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
1073 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
1074 return LoadIconA( hInstance, nameStr );
1078 /***********************************************************************
1079 * CreateCursor16 (USER.406)
1081 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1082 INT16 xHotSpot, INT16 yHotSpot,
1083 INT16 nWidth, INT16 nHeight,
1084 LPCVOID lpANDbits, LPCVOID lpXORbits )
1086 CURSORICONINFO info;
1088 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1089 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1091 info.ptHotSpot.x = xHotSpot;
1092 info.ptHotSpot.y = yHotSpot;
1093 info.nWidth = nWidth;
1094 info.nHeight = nHeight;
1095 info.nWidthBytes = 0;
1097 info.bBitsPerPixel = 1;
1099 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1103 /***********************************************************************
1104 * CreateCursor32 (USER32.67)
1106 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1107 INT xHotSpot, INT yHotSpot,
1108 INT nWidth, INT nHeight,
1109 LPCVOID lpANDbits, LPCVOID lpXORbits )
1111 CURSORICONINFO info;
1113 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1114 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1116 info.ptHotSpot.x = xHotSpot;
1117 info.ptHotSpot.y = yHotSpot;
1118 info.nWidth = nWidth;
1119 info.nHeight = nHeight;
1120 info.nWidthBytes = 0;
1122 info.bBitsPerPixel = 1;
1124 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1128 /***********************************************************************
1129 * CreateIcon16 (USER.407)
1131 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1132 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1133 LPCVOID lpANDbits, LPCVOID lpXORbits )
1135 CURSORICONINFO info;
1137 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1138 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1140 info.ptHotSpot.x = ICON_HOTSPOT;
1141 info.ptHotSpot.y = ICON_HOTSPOT;
1142 info.nWidth = nWidth;
1143 info.nHeight = nHeight;
1144 info.nWidthBytes = 0;
1145 info.bPlanes = bPlanes;
1146 info.bBitsPerPixel = bBitsPixel;
1148 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1152 /***********************************************************************
1153 * CreateIcon32 (USER32.75)
1155 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
1156 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
1157 LPCVOID lpANDbits, LPCVOID lpXORbits )
1159 CURSORICONINFO info;
1161 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1162 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1164 info.ptHotSpot.x = ICON_HOTSPOT;
1165 info.ptHotSpot.y = ICON_HOTSPOT;
1166 info.nWidth = nWidth;
1167 info.nHeight = nHeight;
1168 info.nWidthBytes = 0;
1169 info.bPlanes = bPlanes;
1170 info.bBitsPerPixel = bBitsPixel;
1172 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1176 /***********************************************************************
1177 * CreateCursorIconIndirect (USER.408)
1179 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1180 CURSORICONINFO *info,
1186 int sizeAnd, sizeXor;
1188 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1189 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1190 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1191 sizeXor = info->nHeight * info->nWidthBytes;
1192 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1193 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1194 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1196 if (hInstance) FarSetOwner16( handle, hInstance );
1197 ptr = (char *)GlobalLock16( handle );
1198 memcpy( ptr, info, sizeof(*info) );
1199 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1200 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1201 GlobalUnlock16( handle );
1206 /***********************************************************************
1207 * CopyIcon16 (USER.368)
1209 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1211 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1212 return CURSORICON_Copy( hInstance, hIcon );
1216 /***********************************************************************
1217 * CopyIcon32 (USER32.60)
1219 HICON WINAPI CopyIcon( HICON hIcon )
1221 HTASK16 hTask = GetCurrentTask ();
1222 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1223 TRACE_(icon)("%04x\n", hIcon );
1224 return CURSORICON_Copy( pTask->hInstance, hIcon );
1228 /***********************************************************************
1229 * CopyCursor16 (USER.369)
1231 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1233 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1234 return CURSORICON_Copy( hInstance, hCursor );
1237 /**********************************************************************
1238 * CURSORICON_Destroy (USER.610)
1240 * This routine is actually exported from Win95 USER under the name
1241 * DestroyIcon32 ... The behaviour implemented here should mimic
1242 * the Win95 one exactly, especially the return values, which
1243 * depend on the setting of various flags.
1245 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1249 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1251 /* Check whether destroying active cursor */
1253 if ( hActiveCursor == handle )
1255 ERR_(cursor)("Destroying active cursor!\n" );
1259 /* Try shared cursor/icon first */
1261 if ( !(flags & CID_NONSHARED) )
1263 INT count = CURSORICON_DelSharedIcon( handle );
1266 return (flags & CID_WIN32)? TRUE : (count == 0);
1268 /* FIXME: OEM cursors/icons should be recognized */
1271 /* Now assume non-shared cursor/icon */
1273 retv = GlobalFree16( handle );
1274 return (flags & CID_RESOURCE)? retv : TRUE;
1277 /***********************************************************************
1278 * DestroyIcon16 (USER.457)
1280 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1282 return CURSORICON_Destroy( hIcon, 0 );
1285 /***********************************************************************
1286 * DestroyIcon (USER32.133)
1288 BOOL WINAPI DestroyIcon( HICON hIcon )
1290 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1293 /***********************************************************************
1294 * DestroyCursor16 (USER.458)
1296 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1298 return CURSORICON_Destroy( hCursor, 0 );
1301 /***********************************************************************
1302 * DestroyCursor (USER32.132)
1304 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1306 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1310 /***********************************************************************
1311 * DrawIcon16 (USER.84)
1313 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1315 return DrawIcon( hdc, x, y, hIcon );
1319 /***********************************************************************
1320 * DrawIcon32 (USER32.159)
1322 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1324 CURSORICONINFO *ptr;
1326 HBITMAP hXorBits, hAndBits;
1327 COLORREF oldFg, oldBg;
1329 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1330 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1331 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1333 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1334 ptr->bBitsPerPixel, (char *)(ptr + 1)
1335 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1336 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1337 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1339 if (hXorBits && hAndBits)
1341 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1342 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1343 SelectObject( hMemDC, hXorBits );
1344 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1345 SelectObject( hMemDC, hBitTemp );
1348 if (hXorBits) DeleteObject( hXorBits );
1349 if (hAndBits) DeleteObject( hAndBits );
1350 GlobalUnlock16( hIcon );
1351 SetTextColor( hdc, oldFg );
1352 SetBkColor( hdc, oldBg );
1357 /***********************************************************************
1358 * DumpIcon (USER.459)
1360 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1361 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1363 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1364 int sizeAnd, sizeXor;
1366 if (!info) return 0;
1367 sizeXor = info->nHeight * info->nWidthBytes;
1368 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1369 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1370 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1371 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1372 return MAKELONG( sizeXor, sizeXor );
1376 /***********************************************************************
1377 * SetCursor16 (USER.69)
1379 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1381 return (HCURSOR16)SetCursor( hCursor );
1385 /***********************************************************************
1386 * SetCursor32 (USER32.472)
1388 * A handle to the previous cursor shape.
1390 HCURSOR WINAPI SetCursor(
1391 HCURSOR hCursor /* Handle of cursor to show */
1395 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1396 TRACE_(cursor)("%04x\n", hCursor );
1397 hOldCursor = hActiveCursor;
1398 hActiveCursor = hCursor;
1399 /* Change the cursor shape only if it is visible */
1400 if (CURSOR_ShowCount >= 0)
1402 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1403 GlobalUnlock16( hActiveCursor );
1409 /***********************************************************************
1410 * SetCursorPos16 (USER.70)
1412 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1414 SetCursorPos( x, y );
1418 /***********************************************************************
1419 * SetCursorPos32 (USER32.474)
1421 BOOL WINAPI SetCursorPos( INT x, INT y )
1423 DISPLAY_MoveCursor( x, y );
1428 /***********************************************************************
1429 * ShowCursor16 (USER.71)
1431 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1433 return ShowCursor( bShow );
1437 /***********************************************************************
1438 * ShowCursor32 (USER32.530)
1440 INT WINAPI ShowCursor( BOOL bShow )
1442 TRACE_(cursor)("%d, count=%d\n",
1443 bShow, CURSOR_ShowCount );
1447 if (++CURSOR_ShowCount == 0) /* Show it */
1449 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1450 GlobalUnlock16( hActiveCursor );
1455 if (--CURSOR_ShowCount == -1) /* Hide it */
1456 DISPLAY_SetCursor( NULL );
1458 return CURSOR_ShowCount;
1462 /***********************************************************************
1463 * GetCursor16 (USER.247)
1465 HCURSOR16 WINAPI GetCursor16(void)
1467 return hActiveCursor;
1471 /***********************************************************************
1472 * GetCursor32 (USER32.227)
1474 HCURSOR WINAPI GetCursor(void)
1476 return hActiveCursor;
1480 /***********************************************************************
1481 * ClipCursor16 (USER.16)
1483 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1485 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1486 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1491 /***********************************************************************
1492 * ClipCursor32 (USER32.53)
1494 BOOL WINAPI ClipCursor( const RECT *rect )
1496 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1497 else CopyRect( &CURSOR_ClipRect, rect );
1502 /***********************************************************************
1503 * GetCursorPos16 (USER.17)
1505 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1512 TRACE_(cursor)("ret=%d,%d\n", pt->x, pt->y );
1517 /***********************************************************************
1518 * GetCursorPos32 (USER32.229)
1520 BOOL WINAPI GetCursorPos( POINT *pt )
1525 ret = GetCursorPos16( &pt16 );
1526 if (pt) CONV_POINT16TO32( &pt16, pt );
1527 return ((pt) ? ret : 0);
1531 /***********************************************************************
1532 * GetClipCursor16 (USER.309)
1534 void WINAPI GetClipCursor16( RECT16 *rect )
1536 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1540 /***********************************************************************
1541 * GetClipCursor32 (USER32.221)
1543 BOOL WINAPI GetClipCursor( RECT *rect )
1547 CopyRect( rect, &CURSOR_ClipRect );
1553 /**********************************************************************
1554 * LookupIconIdFromDirectoryEx16 (USER.364)
1556 * FIXME: exact parameter sizes
1558 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1559 INT16 width, INT16 height, UINT16 cFlag )
1561 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1563 if( dir && !dir->idReserved && (dir->idType & 3) )
1565 CURSORICONDIRENTRY* entry;
1570 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1573 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1578 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1580 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1582 if( entry ) retVal = entry->wResId;
1584 else WARN_(cursor)("invalid resource directory\n");
1588 /**********************************************************************
1589 * LookupIconIdFromDirectoryEx32 (USER32.380)
1591 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1592 INT width, INT height, UINT cFlag )
1594 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1597 /**********************************************************************
1598 * LookupIconIdFromDirectory (USER.???)
1600 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1602 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1603 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1604 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1607 /**********************************************************************
1608 * LookupIconIdFromDirectory (USER32.379)
1610 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1612 return LookupIconIdFromDirectoryEx( dir, bIcon,
1613 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1614 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1617 /**********************************************************************
1618 * GetIconID (USER.455)
1620 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1622 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1624 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1625 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1630 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1631 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1633 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1634 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1636 WARN_(cursor)("invalid res type %ld\n", resType );
1641 /**********************************************************************
1642 * LoadCursorIconHandler (USER.336)
1644 * Supposed to load resources of Windows 2.x applications.
1646 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1648 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1649 hResource, hModule, hRsrc);
1650 return (HGLOBAL16)0;
1653 /**********************************************************************
1654 * LoadDIBIconHandler (USER.357)
1656 * RT_ICON resource loader, installed by USER_SignalProc when module
1659 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1661 /* If hResource is zero we must allocate a new memory block, if it's
1662 * non-zero but GlobalLock() returns NULL then it was discarded and
1663 * we have to recommit some memory, otherwise we just need to check
1664 * the block size. See LoadProc() in 16-bit SDK for more.
1667 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1670 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1671 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1672 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1673 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1678 /**********************************************************************
1679 * LoadDIBCursorHandler (USER.356)
1681 * RT_CURSOR resource loader. Same as above.
1683 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1685 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1688 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1689 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1690 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1691 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1696 /**********************************************************************
1697 * LoadIconHandler (USER.456)
1699 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1701 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1703 TRACE_(cursor)("hRes=%04x\n",hResource);
1705 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1706 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1709 /***********************************************************************
1710 * LoadCursorW (USER32.362)
1712 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1714 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1715 LR_SHARED | LR_DEFAULTSIZE );
1718 /***********************************************************************
1719 * LoadCursorA (USER32.359)
1721 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1723 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1724 LR_SHARED | LR_DEFAULTSIZE );
1727 /***********************************************************************
1728 * LoadCursorFromFileW (USER32.361)
1730 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1732 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1733 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1736 /***********************************************************************
1737 * LoadCursorFromFileA (USER32.360)
1739 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1741 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1742 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1745 /***********************************************************************
1746 * LoadIconW (USER32.364)
1748 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1750 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1751 LR_SHARED | LR_DEFAULTSIZE );
1754 /***********************************************************************
1755 * LoadIconA (USER32.363)
1757 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1759 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1760 LR_SHARED | LR_DEFAULTSIZE );
1763 /**********************************************************************
1764 * GetIconInfo16 (USER.395)
1766 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1769 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1771 iconinfo->fIcon = ii32.fIcon;
1772 iconinfo->xHotspot = ii32.xHotspot;
1773 iconinfo->yHotspot = ii32.yHotspot;
1774 iconinfo->hbmMask = ii32.hbmMask;
1775 iconinfo->hbmColor = ii32.hbmColor;
1779 /**********************************************************************
1780 * GetIconInfo32 (USER32.242)
1782 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1783 CURSORICONINFO *ciconinfo;
1785 ciconinfo = GlobalLock16(hIcon);
1789 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1790 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1792 iconinfo->fIcon = TRUE;
1793 iconinfo->xHotspot = 0;
1794 iconinfo->yHotspot = 0;
1798 iconinfo->fIcon = FALSE;
1799 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1800 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1803 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1804 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1805 (char *)(ciconinfo + 1)
1806 + ciconinfo->nHeight *
1807 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1808 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1809 1, 1, (char *)(ciconinfo + 1));
1811 GlobalUnlock16(hIcon);
1816 /**********************************************************************
1817 * CreateIconIndirect (USER32.78)
1819 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1820 BITMAPOBJ *bmpXor,*bmpAnd;
1822 int sizeXor,sizeAnd;
1824 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1825 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1827 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1828 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1830 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1831 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1834 CURSORICONINFO *info;
1836 info = (CURSORICONINFO *)GlobalLock16( hObj );
1838 /* If we are creating an icon, the hotspot is unused */
1839 if (iconinfo->fIcon)
1841 info->ptHotSpot.x = ICON_HOTSPOT;
1842 info->ptHotSpot.y = ICON_HOTSPOT;
1846 info->ptHotSpot.x = iconinfo->xHotspot;
1847 info->ptHotSpot.y = iconinfo->yHotspot;
1850 info->nWidth = bmpXor->bitmap.bmWidth;
1851 info->nHeight = bmpXor->bitmap.bmHeight;
1852 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1853 info->bPlanes = bmpXor->bitmap.bmPlanes;
1854 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1856 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1858 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1859 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1860 GlobalUnlock16( hObj );
1866 /**********************************************************************
1868 DrawIconEx16 (USER.394)
1870 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1871 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1872 HBRUSH16 hbr, UINT16 flags)
1874 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1879 /******************************************************************************
1880 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1883 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1886 * hdc [I] Handle to device context
1887 * x0 [I] X coordinate of upper left corner
1888 * y0 [I] Y coordinate of upper left corner
1889 * hIcon [I] Handle to icon to draw
1890 * cxWidth [I] Width of icon
1891 * cyWidth [I] Height of icon
1892 * istep [I] Index of frame in animated cursor
1893 * hbr [I] Handle to background brush
1894 * flags [I] Icon-drawing flags
1900 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1901 INT cxWidth, INT cyWidth, UINT istep,
1902 HBRUSH hbr, UINT flags )
1904 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1905 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1906 BOOL result = FALSE, DoOffscreen = FALSE;
1907 HBITMAP hB_off = 0, hOld = 0;
1909 if (!ptr) return FALSE;
1912 FIXME_(icon)("Ignoring istep=%d\n", istep);
1913 if (flags & DI_COMPAT)
1914 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1916 /* Calculate the size of the destination image. */
1919 if (flags & DI_DEFAULTSIZE)
1920 cxWidth = GetSystemMetrics (SM_CXICON);
1922 cxWidth = ptr->nWidth;
1926 if (flags & DI_DEFAULTSIZE)
1927 cyWidth = GetSystemMetrics (SM_CYICON);
1929 cyWidth = ptr->nHeight;
1932 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1933 STOCK_HOLLOW_BRUSH)))
1935 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1938 UINT16 magic = object->wMagic;
1939 GDI_HEAP_UNLOCK(hbr);
1940 DoOffscreen = magic == BRUSH_MAGIC;
1951 hDC_off = CreateCompatibleDC(hdc);
1952 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1953 if (hDC_off && hB_off) {
1954 hOld = SelectObject(hDC_off, hB_off);
1955 FillRect(hDC_off, &r, hbr);
1959 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1961 HBITMAP hXorBits, hAndBits;
1962 COLORREF oldFg, oldBg;
1965 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1967 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1968 ptr->bPlanes, ptr->bBitsPerPixel,
1971 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1972 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1973 1, 1, (char *)(ptr+1) );
1974 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1975 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1977 if (hXorBits && hAndBits)
1979 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1980 if (flags & DI_MASK)
1983 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1984 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1986 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1987 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1989 SelectObject( hMemDC, hXorBits );
1990 if (flags & DI_IMAGE)
1993 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1994 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1996 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1997 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1999 SelectObject( hMemDC, hBitTemp );
2003 SetTextColor( hdc, oldFg );
2004 SetBkColor( hdc, oldBg );
2005 if (hXorBits) DeleteObject( hXorBits );
2006 if (hAndBits) DeleteObject( hAndBits );
2007 SetStretchBltMode (hdc, nStretchMode);
2009 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2010 SelectObject(hDC_off, hOld);
2013 if (hMemDC) DeleteDC( hMemDC );
2014 if (hDC_off) DeleteDC(hDC_off);
2015 if (hB_off) DeleteObject(hB_off);
2016 GlobalUnlock16( hIcon );