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 ?!
34 #include "wine/winbase16.h"
38 #include "cursoricon.h"
41 #include "sysmetrics.h"
52 static HCURSOR hActiveCursor = 0; /* Active cursor */
53 static INT CURSOR_ShowCount = 0; /* Cursor display count */
54 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
57 /**********************************************************************
58 * ICONCACHE for cursors/icons loaded with LR_SHARED.
60 * FIXME: This should not be allocated on the system heap, but on a
61 * subsystem-global heap (i.e. one for all Win16 processes,
62 * and one each for every Win32 process).
64 typedef struct tagICONCACHE
66 struct tagICONCACHE *next;
76 static ICONCACHE *IconAnchor = NULL;
77 static CRITICAL_SECTION IconCrst;
79 /**********************************************************************
82 void CURSORICON_Init( void )
84 InitializeCriticalSection( &IconCrst );
85 MakeCriticalSectionGlobal( &IconCrst );
88 /**********************************************************************
89 * CURSORICON_FindSharedIcon
91 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
96 EnterCriticalSection( &IconCrst );
98 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
99 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
102 handle = ptr->handle;
106 LeaveCriticalSection( &IconCrst );
111 /**********************************************************************
112 * CURSORICON_AddSharedIcon
114 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HANDLE handle )
116 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
119 ptr->hModule = hModule;
121 ptr->handle = handle;
124 EnterCriticalSection( &IconCrst );
125 ptr->next = IconAnchor;
127 LeaveCriticalSection( &IconCrst );
130 /**********************************************************************
131 * CURSORICON_DelSharedIcon
133 static INT CURSORICON_DelSharedIcon( HANDLE handle )
138 EnterCriticalSection( &IconCrst );
140 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
141 if ( ptr->handle == handle )
143 if ( ptr->count > 0 ) ptr->count--;
148 LeaveCriticalSection( &IconCrst );
153 /**********************************************************************
154 * CURSORICON_FreeModuleIcons
156 void CURSORICON_FreeModuleIcons( HMODULE hModule )
158 ICONCACHE **ptr = &IconAnchor;
160 if ( HIWORD( hModule ) )
161 hModule = MapHModuleLS( hModule );
163 hModule = GetExePtr( hModule );
165 EnterCriticalSection( &IconCrst );
169 if ( (*ptr)->hModule == hModule )
171 ICONCACHE *freePtr = *ptr;
172 *ptr = freePtr->next;
174 GlobalFree16( freePtr->handle );
175 HeapFree( SystemHeap, 0, freePtr );
181 LeaveCriticalSection( &IconCrst );
184 /**********************************************************************
185 * CURSORICON_FindBestIcon
187 * Find the icon closest to the requested size and number of colors.
189 static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
190 int height, int colors )
192 int i, maxcolors, maxwidth, maxheight;
193 ICONDIRENTRY *entry, *bestEntry = NULL;
195 if (dir->idCount < 1)
197 WARN(icon, "Empty directory!\n" );
200 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
202 /* First find the exact size with less colors */
205 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
206 if ((entry->bWidth == width) && (entry->bHeight == height) &&
207 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
210 maxcolors = entry->bColorCount;
212 if (bestEntry) return bestEntry;
214 /* First find the exact size with more colors */
217 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
218 if ((entry->bWidth == width) && (entry->bHeight == height) &&
219 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
222 maxcolors = entry->bColorCount;
224 if (bestEntry) return bestEntry;
226 /* Now find a smaller one with less colors */
228 maxcolors = maxwidth = maxheight = 0;
229 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
230 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
231 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
232 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
235 maxwidth = entry->bWidth;
236 maxheight = entry->bHeight;
237 maxcolors = entry->bColorCount;
239 if (bestEntry) return bestEntry;
241 /* Now find a smaller one with more colors */
244 maxwidth = maxheight = 0;
245 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
246 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
247 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
248 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
251 maxwidth = entry->bWidth;
252 maxheight = entry->bHeight;
253 maxcolors = entry->bColorCount;
255 if (bestEntry) return bestEntry;
257 /* Now find a larger one with less colors */
260 maxwidth = maxheight = 255;
261 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
262 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
263 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
266 maxwidth = entry->bWidth;
267 maxheight = entry->bHeight;
268 maxcolors = entry->bColorCount;
270 if (bestEntry) return bestEntry;
272 /* Now find a larger one with more colors */
274 maxcolors = maxwidth = maxheight = 255;
275 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
276 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
277 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
280 maxwidth = entry->bWidth;
281 maxheight = entry->bHeight;
282 maxcolors = entry->bColorCount;
289 /**********************************************************************
290 * CURSORICON_FindBestCursor
292 * Find the cursor closest to the requested size.
293 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
296 static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
297 int width, int height, int color)
299 int i, maxwidth, maxheight;
300 CURSORDIRENTRY *entry, *bestEntry = NULL;
302 if (dir->idCount < 1)
304 WARN(cursor, "Empty directory!\n" );
307 if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
309 /* First find the largest one smaller than or equal to the requested size*/
311 maxwidth = maxheight = 0;
312 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
313 if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
314 (entry->wWidth > maxwidth) && (entry->wHeight > maxheight) &&
315 (entry->wBitCount == 1))
318 maxwidth = entry->wWidth;
319 maxheight = entry->wHeight;
321 if (bestEntry) return bestEntry;
323 /* Now find the smallest one larger than the requested size */
325 maxwidth = maxheight = 255;
326 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
327 if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight) &&
328 (entry->wBitCount == 1))
331 maxwidth = entry->wWidth;
332 maxheight = entry->wHeight;
338 /*********************************************************************
339 * The main purpose of this function is to create fake resource directory
340 * and fake resource entries. There are several reasons for this:
341 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
343 * There are some "bad" cursor files which do not have
344 * bColorCount initialized but instead one must read this info
345 * directly from corresponding DIB sections
346 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
348 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
349 CURSORICONDIR **res, LPBYTE **ptr)
352 CURSORICONFILEDIR *bits;
353 int entries, size, i;
357 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
359 /* FIXME: test for inimated icons
360 * hack to load the first icon from the *.ani file
362 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
363 { LPBYTE pos = (LPBYTE) bits;
364 FIXME (cursor,"Animated icons not correctly implemented! %p \n", bits);
367 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
368 { FIXME (cursor,"icon entry found! %p\n", bits);
370 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
374 FIXME (cursor,"icon size ok %p \n", bits);
378 if (pos>=(LPBYTE)bits+766) goto fail;
381 if (!(entries = bits->idCount)) goto fail;
382 (int)_free = size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) *
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].cursor.wWidth=bits->idEntries[i].bWidth;
398 (*res)->idEntries[i].cursor.wHeight=bits->idEntries[i].bHeight;
399 (*res)->idEntries[i].cursor.wPlanes=1;
400 (*res)->idEntries[i].cursor.wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
401 bits->idEntries[i].dwDIBOffset))->biBitCount;
402 (*res)->idEntries[i].cursor.dwBytesInRes = bits->idEntries[i].dwDIBSize;
403 (*res)->idEntries[i].cursor.wResId=i+1;
404 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
405 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
406 _free+=sizeof(POINT16);
408 (*res)->idEntries[i].icon.bWidth=bits->idEntries[i].bWidth;
409 (*res)->idEntries[i].icon.bHeight=bits->idEntries[i].bHeight;
410 (*res)->idEntries[i].icon.bColorCount = bits->idEntries[i].bColorCount;
411 (*res)->idEntries[i].icon.wPlanes=1;
412 (*res)->idEntries[i].icon.wBitCount= ((LPBITMAPINFOHEADER)((LPBYTE)bits +
413 bits->idEntries[i].dwDIBOffset))->biBitCount;
414 (*res)->idEntries[i].icon.dwBytesInRes = bits->idEntries[i].dwDIBSize;
415 (*res)->idEntries[i].icon.wResId=i+1;
417 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
418 (*res)->idEntries[i].icon.dwBytesInRes);
419 _free += (*res)->idEntries[i].icon.dwBytesInRes;
421 UnmapViewOfFile( bits );
424 if (*res) HeapFree( GetProcessHeap(), 0, *res );
425 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
426 UnmapViewOfFile( bits );
431 /**********************************************************************
432 * CURSORICON_CreateFromResource
434 * Create a cursor or icon from in-memory resource template.
436 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
437 * with cbSize parameter as well.
439 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
440 UINT cbSize, BOOL bIcon, DWORD dwVersion,
441 INT width, INT height, UINT loadflags )
443 int sizeAnd, sizeXor;
444 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
445 BITMAPOBJ *bmpXor, *bmpAnd;
446 POINT16 hotspot = { 0 ,0 };
452 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
453 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
454 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
455 if (dwVersion == 0x00020000)
457 FIXME(cursor,"\t2.xx resources are not supported\n");
462 bmi = (BITMAPINFO *)bits;
463 else /* get the hotspot */
465 POINT16 *pt = (POINT16 *)bits;
467 bmi = (BITMAPINFO *)(pt + 1);
469 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
471 if (!width) width = bmi->bmiHeader.biWidth;
472 if (!height) height = bmi->bmiHeader.biHeight/2;
473 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
474 (bmi->bmiHeader.biWidth != width);
476 /* Check bitmap header */
478 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
479 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
480 bmi->bmiHeader.biCompression != BI_RGB) )
482 WARN(cursor,"\tinvalid resource bitmap header.\n");
486 if( (hdc = GetDC( 0 )) )
490 /* Make sure we have room for the monochrome bitmap later on.
491 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
492 * up to and including the biBitCount. In-memory icon resource
493 * format is as follows:
495 * BITMAPINFOHEADER icHeader // DIB header
496 * RGBQUAD icColors[] // Color table
497 * BYTE icXOR[] // DIB bits for XOR mask
498 * BYTE icAND[] // DIB bits for AND mask
501 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
502 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
504 memcpy( pInfo, bmi, size );
505 pInfo->bmiHeader.biHeight /= 2;
507 /* Create the XOR bitmap */
510 if ((hXorBits = CreateCompatibleBitmap(hdc, width, height))) {
512 HDC hMem = CreateCompatibleDC(hdc);
516 hOld = SelectObject(hMem, hXorBits);
517 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
518 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
519 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
520 SelectObject(hMem, hOld);
523 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
525 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
526 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
529 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
530 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
531 bmi->bmiHeader.biBitCount) / 2;
533 pInfo->bmiHeader.biBitCount = 1;
534 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
536 RGBQUAD *rgb = pInfo->bmiColors;
538 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
539 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
540 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
541 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
545 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
547 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
548 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
551 /* Create the AND bitmap */
554 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
556 HDC hMem = CreateCompatibleDC(hdc);
560 hOld = SelectObject(hMem, hAndBits);
561 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
562 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
563 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
564 SelectObject(hMem, hOld);
567 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
569 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
570 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
572 if( !hAndBits ) DeleteObject( hXorBits );
574 HeapFree( GetProcessHeap(), 0, pInfo );
579 if( !hXorBits || !hAndBits )
581 WARN(cursor,"\tunable to create an icon bitmap.\n");
585 /* Now create the CURSORICONINFO structure */
586 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
587 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
588 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
589 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
591 if (hObj) hObj = GlobalReAlloc16( hObj,
592 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
593 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
594 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
597 CURSORICONINFO *info;
599 /* Make it owned by the module */
600 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
602 info = (CURSORICONINFO *)GlobalLock16( hObj );
603 info->ptHotSpot.x = hotspot.x;
604 info->ptHotSpot.y = hotspot.y;
605 info->nWidth = bmpXor->bitmap.bmWidth;
606 info->nHeight = bmpXor->bitmap.bmHeight;
607 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
608 info->bPlanes = bmpXor->bitmap.bmPlanes;
609 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
611 /* Transfer the bitmap bits to the CURSORICONINFO structure */
613 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
614 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
615 GlobalUnlock16( hObj );
618 DeleteObject( hXorBits );
619 DeleteObject( hAndBits );
624 /**********************************************************************
625 * CreateIconFromResourceEx16 (USER.450)
627 * FIXME: not sure about exact parameter types
629 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
630 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
632 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
633 width, height, cFlag);
637 /**********************************************************************
638 * CreateIconFromResource (USER32.76)
640 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
641 BOOL bIcon, DWORD dwVersion)
643 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
647 /**********************************************************************
648 * CreateIconFromResourceEx32 (USER32.77)
650 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
651 BOOL bIcon, DWORD dwVersion,
652 INT width, INT height,
655 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
657 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
658 width, height, cFlag );
662 /**********************************************************************
665 * Load a cursor or icon from resource or file.
667 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
668 INT width, INT height, INT colors,
669 BOOL fCursor, UINT loadflags )
671 HANDLE handle = 0, h = 0;
674 CURSORICONDIRENTRY *dirEntry;
677 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
680 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
683 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
685 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
686 bits = ptr[dirEntry->icon.wResId-1];
687 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->icon.dwBytesInRes,
688 !fCursor, 0x00030000, width, height, loadflags);
689 HeapFree( GetProcessHeap(), 0, dir );
690 HeapFree( GetProcessHeap(), 0, ptr );
693 else if ( !hInstance ) /* Load OEM cursor/icon */
701 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
702 if( ansi[0]=='#') /*Check for '#xxx' name */
704 resid = atoi(ansi+1);
705 HeapFree( GetProcessHeap(), 0, ansi );
709 HeapFree( GetProcessHeap(), 0, ansi );
713 else resid = LOWORD(name);
714 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
715 dc = DC_GetDCPtr( hdc );
716 if (dc->funcs->pLoadOEMResource)
717 h = dc->funcs->pLoadOEMResource( resid, fCursor ?
718 OEM_CURSOR : OEM_ICON );
719 GDI_HEAP_UNLOCK( hdc );
723 else /* Load from resource */
728 /* Normalize hInstance (must be uniquely represented for icon cache) */
730 if ( HIWORD( hInstance ) )
731 hInstance = MapHModuleLS( hInstance );
733 hInstance = GetExePtr( hInstance );
735 /* Get directory resource ID */
737 if (!(hRsrc = FindResourceW( hInstance, name,
738 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
741 /* If shared icon, check whether it was already loaded */
743 if ( (loadflags & LR_SHARED)
744 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
747 /* Find the best entry in the directory */
749 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
750 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
752 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
755 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
756 width, height, colors );
757 if (!dirEntry) return 0;
758 wResId = dirEntry->icon.wResId;
759 dwBytesInRes = dirEntry->icon.dwBytesInRes;
760 FreeResource( handle );
762 /* Load the resource */
764 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
765 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
766 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
767 bits = (LPBYTE)LockResource( handle );
768 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
769 !fCursor, 0x00030000, width, height, loadflags);
770 FreeResource( handle );
772 /* If shared icon, add to icon cache */
774 if ( h && (loadflags & LR_SHARED) )
775 CURSORICON_AddSharedIcon( hInstance, hRsrc, h );
781 /***********************************************************************
784 * Make a copy of a cursor or icon.
786 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
788 char *ptrOld, *ptrNew;
792 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
793 if (!(hInstance = GetExePtr( hInstance ))) return 0;
794 size = GlobalSize16( handle );
795 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
796 FarSetOwner16( hNew, hInstance );
797 ptrNew = (char *)GlobalLock16( hNew );
798 memcpy( ptrNew, ptrOld, size );
799 GlobalUnlock16( handle );
800 GlobalUnlock16( hNew );
804 /***********************************************************************
805 * CURSORICON_IconToCursor
807 * Converts bitmap to mono and truncates if icon is too large (should
808 * probably do StretchBlt() instead).
810 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
813 CURSORICONINFO *pIcon = NULL;
814 HTASK16 hTask = GetCurrentTask();
815 TDB* pTask = (TDB *)GlobalLock16(hTask);
818 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
819 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
820 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
825 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
826 BYTE* psPtr, *pxbPtr = pXorBits;
827 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
833 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
834 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
836 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
837 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
838 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
840 memset(pXorBits, 0, 128);
841 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
842 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
843 cI.nWidth = 32; cI.nHeight = 32;
844 cI.nWidthBytes = 4; /* 32x1bpp */
846 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
847 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
849 for( iy = 0; iy < maxy; iy++ )
851 unsigned shift = iy % 2;
853 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
854 (and_width > 4) ? 4 : and_width );
855 for( ix = 0; ix < maxx; ix++ )
857 if( bSemiTransparent && ((ix+shift)%2) )
859 /* set AND bit, XOR bit stays 0 */
861 pbc = pAndBits + iy * 4 + ix/8;
862 *pbc |= 0x80 >> (ix%8);
866 /* keep AND bit, set XOR bit */
868 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
869 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
870 col = COLOR_ToLogical(val);
871 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
874 *pbc |= 0x80 >> (ix%8);
882 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
884 if( !hRet ) /* fall back on default drag cursor */
885 hRet = CURSORICON_Copy( pTask->hInstance ,
886 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
887 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
894 /***********************************************************************
895 * LoadCursor16 (USER.173)
897 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
899 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
900 return LoadCursorA( hInstance, nameStr );
904 /***********************************************************************
905 * LoadIcon16 (USER.174)
907 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
909 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
910 return LoadIconA( hInstance, nameStr );
914 /***********************************************************************
915 * CreateCursor16 (USER.406)
917 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
918 INT16 xHotSpot, INT16 yHotSpot,
919 INT16 nWidth, INT16 nHeight,
920 LPCVOID lpANDbits, LPCVOID lpXORbits )
922 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
924 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
925 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
926 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
930 /***********************************************************************
931 * CreateCursor32 (USER32.67)
933 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
934 INT xHotSpot, INT yHotSpot,
935 INT nWidth, INT nHeight,
936 LPCVOID lpANDbits, LPCVOID lpXORbits )
938 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
940 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
941 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
942 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
946 /***********************************************************************
947 * CreateIcon16 (USER.407)
949 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
950 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
951 LPCVOID lpANDbits, LPCVOID lpXORbits )
953 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
955 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
956 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
957 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
961 /***********************************************************************
962 * CreateIcon32 (USER32.75)
964 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
965 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
966 LPCVOID lpANDbits, LPCVOID lpXORbits )
968 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
970 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
971 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
972 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
976 /***********************************************************************
977 * CreateCursorIconIndirect (USER.408)
979 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
980 CURSORICONINFO *info,
986 int sizeAnd, sizeXor;
988 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
989 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
990 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
991 sizeXor = info->nHeight * info->nWidthBytes;
992 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
993 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
994 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
996 if (hInstance) FarSetOwner16( handle, hInstance );
997 ptr = (char *)GlobalLock16( handle );
998 memcpy( ptr, info, sizeof(*info) );
999 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1000 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1001 GlobalUnlock16( handle );
1006 /***********************************************************************
1007 * CopyIcon16 (USER.368)
1009 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1011 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
1012 return CURSORICON_Copy( hInstance, hIcon );
1016 /***********************************************************************
1017 * CopyIcon32 (USER32.60)
1019 HICON WINAPI CopyIcon( HICON hIcon )
1021 HTASK16 hTask = GetCurrentTask ();
1022 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1023 TRACE(icon, "%04x\n", hIcon );
1024 return CURSORICON_Copy( pTask->hInstance, hIcon );
1028 /***********************************************************************
1029 * CopyCursor16 (USER.369)
1031 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1033 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
1034 return CURSORICON_Copy( hInstance, hCursor );
1037 /**********************************************************************
1038 * CURSORICON_Destroy (USER.610)
1040 * This routine is actually exported from Win95 USER under the name
1041 * DestroyIcon32 ... The behaviour implemented here should mimic
1042 * the Win95 one exactly, especially the return values, which
1043 * depend on the setting of various flags.
1045 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1049 TRACE( icon, "(%04x, %04x)\n", handle, flags );
1051 /* Check whether destroying active cursor */
1053 if ( hActiveCursor == handle )
1055 ERR( cursor, "Destroying active cursor!\n" );
1059 /* Try shared cursor/icon first */
1061 if ( !(flags & CID_NONSHARED) )
1063 INT count = CURSORICON_DelSharedIcon( handle );
1066 return (flags & CID_WIN32)? TRUE : (count == 0);
1068 /* FIXME: OEM cursors/icons should be recognized */
1071 /* Now assume non-shared cursor/icon */
1073 retv = GlobalFree16( handle );
1074 return (flags & CID_RESOURCE)? retv : TRUE;
1077 /***********************************************************************
1078 * DestroyIcon16 (USER.457)
1080 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1082 return CURSORICON_Destroy( hIcon, 0 );
1085 /***********************************************************************
1086 * DestroyIcon (USER32.133)
1088 BOOL WINAPI DestroyIcon( HICON hIcon )
1090 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1093 /***********************************************************************
1094 * DestroyCursor16 (USER.458)
1096 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1098 return CURSORICON_Destroy( hCursor, 0 );
1101 /***********************************************************************
1102 * DestroyCursor (USER32.132)
1104 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1106 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1110 /***********************************************************************
1111 * DrawIcon16 (USER.84)
1113 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1115 return DrawIcon( hdc, x, y, hIcon );
1119 /***********************************************************************
1120 * DrawIcon32 (USER32.159)
1122 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1124 CURSORICONINFO *ptr;
1126 HBITMAP hXorBits, hAndBits;
1127 COLORREF oldFg, oldBg;
1129 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1130 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1131 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1133 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1134 ptr->bBitsPerPixel, (char *)(ptr + 1)
1135 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1136 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1137 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1139 if (hXorBits && hAndBits)
1141 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1142 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1143 SelectObject( hMemDC, hXorBits );
1144 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1145 SelectObject( hMemDC, hBitTemp );
1148 if (hXorBits) DeleteObject( hXorBits );
1149 if (hAndBits) DeleteObject( hAndBits );
1150 GlobalUnlock16( hIcon );
1151 SetTextColor( hdc, oldFg );
1152 SetBkColor( hdc, oldBg );
1157 /***********************************************************************
1158 * DumpIcon (USER.459)
1160 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1161 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1163 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1164 int sizeAnd, sizeXor;
1166 if (!info) return 0;
1167 sizeXor = info->nHeight * info->nWidthBytes;
1168 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1169 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1170 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1171 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1172 return MAKELONG( sizeXor, sizeXor );
1176 /***********************************************************************
1177 * SetCursor16 (USER.69)
1179 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1181 return (HCURSOR16)SetCursor( hCursor );
1185 /***********************************************************************
1186 * SetCursor32 (USER32.472)
1188 * A handle to the previous cursor shape.
1190 HCURSOR WINAPI SetCursor(
1191 HCURSOR hCursor /* Handle of cursor to show */
1195 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1196 TRACE(cursor, "%04x\n", hCursor );
1197 hOldCursor = hActiveCursor;
1198 hActiveCursor = hCursor;
1199 /* Change the cursor shape only if it is visible */
1200 if (CURSOR_ShowCount >= 0)
1202 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1203 GlobalUnlock16( hActiveCursor );
1209 /***********************************************************************
1210 * SetCursorPos16 (USER.70)
1212 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1214 SetCursorPos( x, y );
1218 /***********************************************************************
1219 * SetCursorPos32 (USER32.474)
1221 BOOL WINAPI SetCursorPos( INT x, INT y )
1223 DISPLAY_MoveCursor( x, y );
1228 /***********************************************************************
1229 * ShowCursor16 (USER.71)
1231 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1233 return ShowCursor( bShow );
1237 /***********************************************************************
1238 * ShowCursor32 (USER32.530)
1240 INT WINAPI ShowCursor( BOOL bShow )
1242 TRACE(cursor, "%d, count=%d\n",
1243 bShow, CURSOR_ShowCount );
1247 if (++CURSOR_ShowCount == 0) /* Show it */
1249 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1250 GlobalUnlock16( hActiveCursor );
1255 if (--CURSOR_ShowCount == -1) /* Hide it */
1256 DISPLAY_SetCursor( NULL );
1258 return CURSOR_ShowCount;
1262 /***********************************************************************
1263 * GetCursor16 (USER.247)
1265 HCURSOR16 WINAPI GetCursor16(void)
1267 return hActiveCursor;
1271 /***********************************************************************
1272 * GetCursor32 (USER32.227)
1274 HCURSOR WINAPI GetCursor(void)
1276 return hActiveCursor;
1280 /***********************************************************************
1281 * ClipCursor16 (USER.16)
1283 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1285 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1286 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1291 /***********************************************************************
1292 * ClipCursor32 (USER32.53)
1294 BOOL WINAPI ClipCursor( const RECT *rect )
1296 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1297 else CopyRect( &CURSOR_ClipRect, rect );
1302 /***********************************************************************
1303 * GetCursorPos16 (USER.17)
1305 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1307 DWORD posX, posY, state;
1310 if (!EVENT_QueryPointer( &posX, &posY, &state ))
1316 if (state & MK_LBUTTON)
1317 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1319 MouseButtonsStates[0] = FALSE;
1320 if (state & MK_MBUTTON)
1321 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1323 MouseButtonsStates[1] = FALSE;
1324 if (state & MK_RBUTTON)
1325 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1327 MouseButtonsStates[2] = FALSE;
1329 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1334 /***********************************************************************
1335 * GetCursorPos32 (USER32.229)
1337 BOOL WINAPI GetCursorPos( POINT *pt )
1342 ret = GetCursorPos16( &pt16 );
1343 if (pt) CONV_POINT16TO32( &pt16, pt );
1344 return ((pt) ? ret : 0);
1348 /***********************************************************************
1349 * GetClipCursor16 (USER.309)
1351 void WINAPI GetClipCursor16( RECT16 *rect )
1353 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1357 /***********************************************************************
1358 * GetClipCursor32 (USER32.221)
1360 BOOL WINAPI GetClipCursor( RECT *rect )
1364 CopyRect( rect, &CURSOR_ClipRect );
1370 /**********************************************************************
1371 * LookupIconIdFromDirectoryEx16 (USER.364)
1373 * FIXME: exact parameter sizes
1375 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1376 INT16 width, INT16 height, UINT16 cFlag )
1378 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1380 if( dir && !dir->idReserved && (dir->idType & 3) )
1383 UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1384 int colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1389 ICONDIRENTRY* entry;
1390 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1391 if( entry ) retVal = entry->wResId;
1395 CURSORDIRENTRY* entry;
1396 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1397 if( entry ) retVal = entry->wResId;
1400 else WARN(cursor, "invalid resource directory\n");
1404 /**********************************************************************
1405 * LookupIconIdFromDirectoryEx32 (USER32.380)
1407 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1408 INT width, INT height, UINT cFlag )
1410 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1413 /**********************************************************************
1414 * LookupIconIdFromDirectory (USER.???)
1416 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1418 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1419 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1420 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1423 /**********************************************************************
1424 * LookupIconIdFromDirectory (USER32.379)
1426 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1428 return LookupIconIdFromDirectoryEx( dir, bIcon,
1429 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1430 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1433 /**********************************************************************
1434 * GetIconID (USER.455)
1436 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1438 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1440 TRACE(cursor, "hRes=%04x, entries=%i\n",
1441 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1446 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1447 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1449 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1450 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1452 WARN(cursor, "invalid res type %ld\n", resType );
1457 /**********************************************************************
1458 * LoadCursorIconHandler (USER.336)
1460 * Supposed to load resources of Windows 2.x applications.
1462 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1464 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1465 hResource, hModule, hRsrc);
1466 return (HGLOBAL16)0;
1469 /**********************************************************************
1470 * LoadDIBIconHandler (USER.357)
1472 * RT_ICON resource loader, installed by USER_SignalProc when module
1475 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1477 /* If hResource is zero we must allocate a new memory block, if it's
1478 * non-zero but GlobalLock() returns NULL then it was discarded and
1479 * we have to recommit some memory, otherwise we just need to check
1480 * the block size. See LoadProc() in 16-bit SDK for more.
1483 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1486 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1487 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1488 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1489 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1494 /**********************************************************************
1495 * LoadDIBCursorHandler (USER.356)
1497 * RT_CURSOR resource loader. Same as above.
1499 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1501 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1504 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1505 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1506 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1507 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1512 /**********************************************************************
1513 * LoadIconHandler (USER.456)
1515 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1517 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1519 TRACE(cursor,"hRes=%04x\n",hResource);
1521 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1522 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1525 /***********************************************************************
1526 * LoadCursorW (USER32.362)
1528 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1530 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1531 LR_SHARED | LR_DEFAULTSIZE );
1534 /***********************************************************************
1535 * LoadCursorA (USER32.359)
1537 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1539 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1540 LR_SHARED | LR_DEFAULTSIZE );
1543 /***********************************************************************
1544 * LoadCursorFromFileW (USER32.361)
1546 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1548 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1549 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1552 /***********************************************************************
1553 * LoadCursorFromFileA (USER32.360)
1555 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1557 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1558 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1561 /***********************************************************************
1562 * LoadIconW (USER32.364)
1564 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1566 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1567 LR_SHARED | LR_DEFAULTSIZE );
1570 /***********************************************************************
1571 * LoadIconA (USER32.363)
1573 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1575 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1576 LR_SHARED | LR_DEFAULTSIZE );
1579 /**********************************************************************
1580 * GetIconInfo16 (USER.395)
1582 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1585 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1587 iconinfo->fIcon = ii32.fIcon;
1588 iconinfo->xHotspot = ii32.xHotspot;
1589 iconinfo->yHotspot = ii32.yHotspot;
1590 iconinfo->hbmMask = ii32.hbmMask;
1591 iconinfo->hbmColor = ii32.hbmColor;
1595 /**********************************************************************
1596 * GetIconInfo32 (USER32.242)
1598 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1599 CURSORICONINFO *ciconinfo;
1601 ciconinfo = GlobalLock16(hIcon);
1604 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1605 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1606 iconinfo->fIcon = TRUE; /* hmm */
1608 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1609 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1610 (char *)(ciconinfo + 1)
1611 + ciconinfo->nHeight *
1612 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1613 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1614 1, 1, (char *)(ciconinfo + 1));
1616 GlobalUnlock16(hIcon);
1621 /**********************************************************************
1622 * CreateIconIndirect (USER32.78)
1624 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1625 BITMAPOBJ *bmpXor,*bmpAnd;
1627 int sizeXor,sizeAnd;
1629 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1630 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1632 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1633 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1635 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1636 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1639 CURSORICONINFO *info;
1641 info = (CURSORICONINFO *)GlobalLock16( hObj );
1642 info->ptHotSpot.x = iconinfo->xHotspot;
1643 info->ptHotSpot.y = iconinfo->yHotspot;
1644 info->nWidth = bmpXor->bitmap.bmWidth;
1645 info->nHeight = bmpXor->bitmap.bmHeight;
1646 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1647 info->bPlanes = bmpXor->bitmap.bmPlanes;
1648 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1650 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1652 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1653 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1654 GlobalUnlock16( hObj );
1660 /**********************************************************************
1662 DrawIconEx16 (USER.394)
1664 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1665 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1666 HBRUSH16 hbr, UINT16 flags)
1668 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1673 /******************************************************************************
1674 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1677 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1680 * hdc [I] Handle to device context
1681 * x0 [I] X coordinate of upper left corner
1682 * y0 [I] Y coordinate of upper left corner
1683 * hIcon [I] Handle to icon to draw
1684 * cxWidth [I] Width of icon
1685 * cyWidth [I] Height of icon
1686 * istep [I] Index of frame in animated cursor
1687 * hbr [I] Handle to background brush
1688 * flags [I] Icon-drawing flags
1694 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1695 INT cxWidth, INT cyWidth, UINT istep,
1696 HBRUSH hbr, UINT flags )
1698 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1699 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1700 BOOL result = FALSE, DoOffscreen = FALSE;
1701 HBITMAP hB_off = 0, hOld = 0;
1703 if (!ptr) return FALSE;
1706 FIXME(icon, "Ignoring istep=%d\n", istep);
1707 if (flags & DI_COMPAT)
1708 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1710 /* Calculate the size of the destination image. */
1713 if (flags & DI_DEFAULTSIZE)
1714 cxWidth = GetSystemMetrics (SM_CXICON);
1716 cxWidth = ptr->nWidth;
1720 if (flags & DI_DEFAULTSIZE)
1721 cyWidth = GetSystemMetrics (SM_CYICON);
1723 cyWidth = ptr->nHeight;
1726 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1727 STOCK_HOLLOW_BRUSH)))
1729 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1732 UINT16 magic = object->wMagic;
1733 GDI_HEAP_UNLOCK(hbr);
1734 DoOffscreen = magic == BRUSH_MAGIC;
1738 RECT r = {0, 0, cxWidth, cxWidth};
1740 hDC_off = CreateCompatibleDC(hdc);
1741 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1742 if (hDC_off && hB_off) {
1743 hOld = SelectObject(hDC_off, hB_off);
1744 FillRect(hDC_off, &r, hbr);
1748 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1750 HBITMAP hXorBits, hAndBits;
1751 COLORREF oldFg, oldBg;
1754 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1756 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1757 ptr->bPlanes, ptr->bBitsPerPixel,
1760 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1761 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1762 1, 1, (char *)(ptr+1) );
1763 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1764 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1766 if (hXorBits && hAndBits)
1768 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1769 if (flags & DI_MASK)
1772 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1773 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1775 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1776 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1778 SelectObject( hMemDC, hXorBits );
1779 if (flags & DI_IMAGE)
1782 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1783 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1785 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1786 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1788 SelectObject( hMemDC, hBitTemp );
1792 SetTextColor( hdc, oldFg );
1793 SetBkColor( hdc, oldBg );
1794 if (hXorBits) DeleteObject( hXorBits );
1795 if (hAndBits) DeleteObject( hAndBits );
1796 SetStretchBltMode (hdc, nStretchMode);
1798 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1799 SelectObject(hDC_off, hOld);
1802 if (hMemDC) DeleteDC( hMemDC );
1803 if (hDC_off) DeleteDC(hDC_off);
1804 if (hB_off) DeleteObject(hB_off);
1805 GlobalUnlock16( hIcon );