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 ?!
35 #include "wine/winbase16.h"
36 #include "wine/winuser16.h"
40 #include "cursoricon.h"
43 #include "sysmetrics.h"
54 DECLARE_DEBUG_CHANNEL(cursor)
55 DECLARE_DEBUG_CHANNEL(icon)
57 static HCURSOR hActiveCursor = 0; /* Active cursor */
58 static INT CURSOR_ShowCount = 0; /* Cursor display count */
59 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
62 /**********************************************************************
63 * ICONCACHE for cursors/icons loaded with LR_SHARED.
65 * FIXME: This should not be allocated on the system heap, but on a
66 * subsystem-global heap (i.e. one for all Win16 processes,
67 * and one each for every Win32 process).
69 typedef struct tagICONCACHE
71 struct tagICONCACHE *next;
81 static ICONCACHE *IconAnchor = NULL;
82 static CRITICAL_SECTION IconCrst;
84 /**********************************************************************
87 void CURSORICON_Init( void )
89 InitializeCriticalSection( &IconCrst );
90 MakeCriticalSectionGlobal( &IconCrst );
93 /**********************************************************************
94 * CURSORICON_FindSharedIcon
96 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
101 EnterCriticalSection( &IconCrst );
103 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
104 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
107 handle = ptr->handle;
111 LeaveCriticalSection( &IconCrst );
116 /**********************************************************************
117 * CURSORICON_AddSharedIcon
119 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HANDLE handle )
121 ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
124 ptr->hModule = hModule;
126 ptr->handle = handle;
129 EnterCriticalSection( &IconCrst );
130 ptr->next = IconAnchor;
132 LeaveCriticalSection( &IconCrst );
135 /**********************************************************************
136 * CURSORICON_DelSharedIcon
138 static INT CURSORICON_DelSharedIcon( HANDLE handle )
143 EnterCriticalSection( &IconCrst );
145 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
146 if ( ptr->handle == handle )
148 if ( ptr->count > 0 ) ptr->count--;
153 LeaveCriticalSection( &IconCrst );
158 /**********************************************************************
159 * CURSORICON_FreeModuleIcons
161 void CURSORICON_FreeModuleIcons( HMODULE hModule )
163 ICONCACHE **ptr = &IconAnchor;
165 if ( HIWORD( hModule ) )
166 hModule = MapHModuleLS( hModule );
168 hModule = GetExePtr( hModule );
170 EnterCriticalSection( &IconCrst );
174 if ( (*ptr)->hModule == hModule )
176 ICONCACHE *freePtr = *ptr;
177 *ptr = freePtr->next;
179 GlobalFree16( freePtr->handle );
180 HeapFree( SystemHeap, 0, freePtr );
186 LeaveCriticalSection( &IconCrst );
189 /**********************************************************************
190 * CURSORICON_FindBestIcon
192 * Find the icon closest to the requested size and number of colors.
194 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
195 int height, int colors )
197 int i, maxcolors, maxwidth, maxheight;
198 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
200 if (dir->idCount < 1)
202 WARN(icon, "Empty directory!\n" );
205 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
207 /* First find the exact size with less colors */
210 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
211 if ((entry->ResInfo.icon.bWidth == width) && (entry->ResInfo.icon.bHeight == height) &&
212 (entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
215 maxcolors = entry->ResInfo.icon.bColorCount;
217 if (bestEntry) return bestEntry;
219 /* First find the exact size with more colors */
222 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
223 if ((entry->ResInfo.icon.bWidth == width) && (entry->ResInfo.icon.bHeight == height) &&
224 (entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
227 maxcolors = entry->ResInfo.icon.bColorCount;
229 if (bestEntry) return bestEntry;
231 /* Now find a smaller one with less colors */
233 maxcolors = maxwidth = maxheight = 0;
234 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
235 if ((entry->ResInfo.icon.bWidth <= width) && (entry->ResInfo.icon.bHeight <= height) &&
236 (entry->ResInfo.icon.bWidth >= maxwidth) && (entry->ResInfo.icon.bHeight >= maxheight) &&
237 (entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
240 maxwidth = entry->ResInfo.icon.bWidth;
241 maxheight = entry->ResInfo.icon.bHeight;
242 maxcolors = entry->ResInfo.icon.bColorCount;
244 if (bestEntry) return bestEntry;
246 /* Now find a smaller one with more colors */
249 maxwidth = maxheight = 0;
250 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
251 if ((entry->ResInfo.icon.bWidth <= width) && (entry->ResInfo.icon.bHeight <= height) &&
252 (entry->ResInfo.icon.bWidth >= maxwidth) && (entry->ResInfo.icon.bHeight >= maxheight) &&
253 (entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
256 maxwidth = entry->ResInfo.icon.bWidth;
257 maxheight = entry->ResInfo.icon.bHeight;
258 maxcolors = entry->ResInfo.icon.bColorCount;
260 if (bestEntry) return bestEntry;
262 /* Now find a larger one with less colors */
265 maxwidth = maxheight = 255;
266 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
267 if ((entry->ResInfo.icon.bWidth <= maxwidth) && (entry->ResInfo.icon.bHeight <= maxheight) &&
268 (entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
271 maxwidth = entry->ResInfo.icon.bWidth;
272 maxheight = entry->ResInfo.icon.bHeight;
273 maxcolors = entry->ResInfo.icon.bColorCount;
275 if (bestEntry) return bestEntry;
277 /* Now find a larger one with more colors */
279 maxcolors = maxwidth = maxheight = 255;
280 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
281 if ((entry->ResInfo.icon.bWidth <= maxwidth) && (entry->ResInfo.icon.bHeight <= maxheight) &&
282 (entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
285 maxwidth = entry->ResInfo.icon.bWidth;
286 maxheight = entry->ResInfo.icon.bHeight;
287 maxcolors = entry->ResInfo.icon.bColorCount;
294 /**********************************************************************
295 * CURSORICON_FindBestCursor
297 * Find the cursor closest to the requested size.
298 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
301 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
302 int width, int height, int color)
304 int i, maxwidth, maxheight;
305 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
307 if (dir->idCount < 1)
309 WARN(cursor, "Empty directory!\n" );
312 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
314 /* First find the largest one smaller than or equal to the requested size*/
316 maxwidth = maxheight = 0;
317 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
318 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
319 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
320 (entry->wBitCount == 1))
323 maxwidth = entry->ResInfo.cursor.wWidth;
324 maxheight = entry->ResInfo.cursor.wHeight;
326 if (bestEntry) return bestEntry;
328 /* Now find the smallest one larger than the requested size */
330 maxwidth = maxheight = 255;
331 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
332 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
333 (entry->wBitCount == 1))
336 maxwidth = entry->ResInfo.cursor.wWidth;
337 maxheight = entry->ResInfo.cursor.wHeight;
343 /*********************************************************************
344 * The main purpose of this function is to create fake resource directory
345 * and fake resource entries. There are several reasons for this:
346 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
348 * There are some "bad" cursor files which do not have
349 * bColorCount initialized but instead one must read this info
350 * directly from corresponding DIB sections
351 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
353 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
354 CURSORICONDIR **res, LPBYTE **ptr)
357 CURSORICONFILEDIR *bits;
358 int entries, size, i;
362 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
364 /* FIXME: test for inimated icons
365 * hack to load the first icon from the *.ani file
367 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
368 { LPBYTE pos = (LPBYTE) bits;
369 FIXME (cursor,"Animated icons not correctly implemented! %p \n", bits);
372 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
373 { FIXME (cursor,"icon entry found! %p\n", bits);
375 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
379 FIXME (cursor,"icon size ok %p \n", bits);
383 if (pos>=(LPBYTE)bits+766) goto fail;
386 if (!(entries = bits->idCount)) goto fail;
387 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
388 _free = (LPBYTE) size;
390 for (i=0; i < entries; i++)
391 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
393 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
394 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
395 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
397 _free = (LPBYTE)(*res) + (int)_free;
398 memcpy((*res), bits, 6);
399 for (i=0; i<entries; i++)
401 ((LPBYTE*)(*ptr))[i] = _free;
403 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
404 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
405 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
406 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
407 _free+=sizeof(POINT16);
409 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
410 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
411 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
413 (*res)->idEntries[i].wPlanes=1;
414 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
415 bits->idEntries[i].dwDIBOffset))->biBitCount;
416 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
417 (*res)->idEntries[i].wResId=i+1;
419 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
420 (*res)->idEntries[i].dwBytesInRes);
421 _free += (*res)->idEntries[i].dwBytesInRes;
423 UnmapViewOfFile( bits );
426 if (*res) HeapFree( GetProcessHeap(), 0, *res );
427 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
428 UnmapViewOfFile( bits );
433 /**********************************************************************
434 * CURSORICON_CreateFromResource
436 * Create a cursor or icon from in-memory resource template.
438 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
439 * with cbSize parameter as well.
441 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
442 UINT cbSize, BOOL bIcon, DWORD dwVersion,
443 INT width, INT height, UINT loadflags )
445 int sizeAnd, sizeXor;
446 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
447 BITMAPOBJ *bmpXor, *bmpAnd;
448 POINT16 hotspot = { 0 ,0 };
454 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
455 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
456 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
457 if (dwVersion == 0x00020000)
459 FIXME(cursor,"\t2.xx resources are not supported\n");
464 bmi = (BITMAPINFO *)bits;
465 else /* get the hotspot */
467 POINT16 *pt = (POINT16 *)bits;
469 bmi = (BITMAPINFO *)(pt + 1);
471 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
473 if (!width) width = bmi->bmiHeader.biWidth;
474 if (!height) height = bmi->bmiHeader.biHeight/2;
475 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
476 (bmi->bmiHeader.biWidth != width);
478 /* Check bitmap header */
480 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
481 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
482 bmi->bmiHeader.biCompression != BI_RGB) )
484 WARN(cursor,"\tinvalid resource bitmap header.\n");
488 if( (hdc = GetDC( 0 )) )
492 /* Make sure we have room for the monochrome bitmap later on.
493 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
494 * up to and including the biBitCount. In-memory icon resource
495 * format is as follows:
497 * BITMAPINFOHEADER icHeader // DIB header
498 * RGBQUAD icColors[] // Color table
499 * BYTE icXOR[] // DIB bits for XOR mask
500 * BYTE icAND[] // DIB bits for AND mask
503 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
504 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
506 memcpy( pInfo, bmi, size );
507 pInfo->bmiHeader.biHeight /= 2;
509 /* Create the XOR bitmap */
512 if ((hXorBits = CreateCompatibleBitmap(hdc, width, height))) {
514 HDC hMem = CreateCompatibleDC(hdc);
518 hOld = SelectObject(hMem, hXorBits);
519 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
520 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
521 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
522 SelectObject(hMem, hOld);
525 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
527 } else hXorBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
528 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
531 char* bits = (char *)bmi + size +
532 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
533 bmi->bmiHeader.biHeight,
534 bmi->bmiHeader.biBitCount) / 2;
536 pInfo->bmiHeader.biBitCount = 1;
537 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
539 RGBQUAD *rgb = pInfo->bmiColors;
541 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
542 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
543 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
544 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
548 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
550 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
551 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
554 /* Create the AND bitmap */
557 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
559 HDC hMem = CreateCompatibleDC(hdc);
563 hOld = SelectObject(hMem, hAndBits);
564 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0,
565 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
566 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
567 SelectObject(hMem, hOld);
570 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
572 } else hAndBits = CreateDIBitmap( hdc, &pInfo->bmiHeader,
573 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
575 if( !hAndBits ) DeleteObject( hXorBits );
577 HeapFree( GetProcessHeap(), 0, pInfo );
582 if( !hXorBits || !hAndBits )
584 WARN(cursor,"\tunable to create an icon bitmap.\n");
588 /* Now create the CURSORICONINFO structure */
589 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
590 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
591 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
592 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
594 if (hObj) hObj = GlobalReAlloc16( hObj,
595 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
596 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
597 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
600 CURSORICONINFO *info;
602 /* Make it owned by the module */
603 if (hInstance) FarSetOwner16( hObj, GetExePtr(hInstance) );
605 info = (CURSORICONINFO *)GlobalLock16( hObj );
606 info->ptHotSpot.x = hotspot.x;
607 info->ptHotSpot.y = hotspot.y;
608 info->nWidth = bmpXor->bitmap.bmWidth;
609 info->nHeight = bmpXor->bitmap.bmHeight;
610 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
611 info->bPlanes = bmpXor->bitmap.bmPlanes;
612 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
614 /* Transfer the bitmap bits to the CURSORICONINFO structure */
616 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
617 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
618 GlobalUnlock16( hObj );
621 DeleteObject( hXorBits );
622 DeleteObject( hAndBits );
627 /**********************************************************************
628 * CreateIconFromResourceEx16 (USER.450)
630 * FIXME: not sure about exact parameter types
632 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
633 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
635 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
636 width, height, cFlag);
640 /**********************************************************************
641 * CreateIconFromResource (USER32.76)
643 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
644 BOOL bIcon, DWORD dwVersion)
646 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
650 /**********************************************************************
651 * CreateIconFromResourceEx32 (USER32.77)
653 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
654 BOOL bIcon, DWORD dwVersion,
655 INT width, INT height,
658 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
660 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
661 width, height, cFlag );
665 /**********************************************************************
668 * Load a cursor or icon from resource or file.
670 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
671 INT width, INT height, INT colors,
672 BOOL fCursor, UINT loadflags )
674 HANDLE handle = 0, h = 0;
677 CURSORICONDIRENTRY *dirEntry;
680 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
683 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
686 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
688 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
689 bits = ptr[dirEntry->wResId-1];
690 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
691 !fCursor, 0x00030000, width, height, loadflags);
692 HeapFree( GetProcessHeap(), 0, dir );
693 HeapFree( GetProcessHeap(), 0, ptr );
696 else if ( !hInstance ) /* Load OEM cursor/icon */
704 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
705 if( ansi[0]=='#') /*Check for '#xxx' name */
707 resid = atoi(ansi+1);
708 HeapFree( GetProcessHeap(), 0, ansi );
712 HeapFree( GetProcessHeap(), 0, ansi );
716 else resid = LOWORD(name);
717 hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
718 dc = DC_GetDCPtr( hdc );
719 if (dc->funcs->pLoadOEMResource)
720 h = dc->funcs->pLoadOEMResource( resid, fCursor ?
721 OEM_CURSOR : OEM_ICON );
722 GDI_HEAP_UNLOCK( hdc );
726 else /* Load from resource */
731 /* Normalize hInstance (must be uniquely represented for icon cache) */
733 if ( HIWORD( hInstance ) )
734 hInstance = MapHModuleLS( hInstance );
736 hInstance = GetExePtr( hInstance );
738 /* Get directory resource ID */
740 if (!(hRsrc = FindResourceW( hInstance, name,
741 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
744 /* If shared icon, check whether it was already loaded */
746 if ( (loadflags & LR_SHARED)
747 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
750 /* Find the best entry in the directory */
752 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
753 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
755 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
758 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
759 width, height, colors );
760 if (!dirEntry) return 0;
761 wResId = dirEntry->wResId;
762 dwBytesInRes = dirEntry->dwBytesInRes;
763 FreeResource( handle );
765 /* Load the resource */
767 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
768 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
769 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
770 bits = (LPBYTE)LockResource( handle );
771 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
772 !fCursor, 0x00030000, width, height, loadflags);
773 FreeResource( handle );
775 /* If shared icon, add to icon cache */
777 if ( h && (loadflags & LR_SHARED) )
778 CURSORICON_AddSharedIcon( hInstance, hRsrc, h );
784 /***********************************************************************
787 * Make a copy of a cursor or icon.
789 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
791 char *ptrOld, *ptrNew;
795 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
796 if (!(hInstance = GetExePtr( hInstance ))) return 0;
797 size = GlobalSize16( handle );
798 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
799 FarSetOwner16( hNew, hInstance );
800 ptrNew = (char *)GlobalLock16( hNew );
801 memcpy( ptrNew, ptrOld, size );
802 GlobalUnlock16( handle );
803 GlobalUnlock16( hNew );
807 /***********************************************************************
808 * CURSORICON_IconToCursor
810 * Converts bitmap to mono and truncates if icon is too large (should
811 * probably do StretchBlt() instead).
813 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
816 CURSORICONINFO *pIcon = NULL;
817 HTASK16 hTask = GetCurrentTask();
818 TDB* pTask = (TDB *)GlobalLock16(hTask);
821 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
822 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
823 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
828 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
829 BYTE* psPtr, *pxbPtr = pXorBits;
830 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
835 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
836 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
838 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
839 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
840 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
842 memset(pXorBits, 0, 128);
843 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
844 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
845 cI.nWidth = 32; cI.nHeight = 32;
846 cI.nWidthBytes = 4; /* 32x1bpp */
848 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
849 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
851 for( iy = 0; iy < maxy; iy++ )
853 unsigned shift = iy % 2;
855 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
856 (and_width > 4) ? 4 : and_width );
857 for( ix = 0; ix < maxx; ix++ )
859 if( bSemiTransparent && ((ix+shift)%2) )
861 /* set AND bit, XOR bit stays 0 */
863 pbc = pAndBits + iy * 4 + ix/8;
864 *pbc |= 0x80 >> (ix%8);
868 /* keep AND bit, set XOR bit */
870 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
871 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
872 if(!PALETTE_Driver->pIsDark(val))
875 *pbc |= 0x80 >> (ix%8);
883 hRet = CreateCursorIconIndirect16( pTask->hInstance , &cI, pAndBits, pXorBits);
885 if( !hRet ) /* fall back on default drag cursor */
886 hRet = CURSORICON_Copy( pTask->hInstance ,
887 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
888 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
895 /***********************************************************************
896 * LoadCursor16 (USER.173)
898 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
900 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
901 return LoadCursorA( hInstance, nameStr );
905 /***********************************************************************
906 * LoadIcon16 (USER.174)
908 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
910 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
911 return LoadIconA( hInstance, nameStr );
915 /***********************************************************************
916 * CreateCursor16 (USER.406)
918 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
919 INT16 xHotSpot, INT16 yHotSpot,
920 INT16 nWidth, INT16 nHeight,
921 LPCVOID lpANDbits, LPCVOID lpXORbits )
925 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
926 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
928 info.ptHotSpot.x = xHotSpot;
929 info.ptHotSpot.y = yHotSpot;
930 info.nWidth = nWidth;
931 info.nHeight = nHeight;
932 info.nWidthBytes = 0;
934 info.bBitsPerPixel = 1;
936 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
940 /***********************************************************************
941 * CreateCursor32 (USER32.67)
943 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
944 INT xHotSpot, INT yHotSpot,
945 INT nWidth, INT nHeight,
946 LPCVOID lpANDbits, LPCVOID lpXORbits )
950 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
951 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
953 info.ptHotSpot.x = xHotSpot;
954 info.ptHotSpot.y = yHotSpot;
955 info.nWidth = nWidth;
956 info.nHeight = nHeight;
957 info.nWidthBytes = 0;
959 info.bBitsPerPixel = 1;
961 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
965 /***********************************************************************
966 * CreateIcon16 (USER.407)
968 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
969 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
970 LPCVOID lpANDbits, LPCVOID lpXORbits )
974 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
975 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
977 info.ptHotSpot.x = 0;
978 info.ptHotSpot.y = 0;
979 info.nWidth = nWidth;
980 info.nHeight = nHeight;
981 info.nWidthBytes = 0;
982 info.bPlanes = bPlanes;
983 info.bBitsPerPixel = bBitsPixel;
985 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
989 /***********************************************************************
990 * CreateIcon32 (USER32.75)
992 HICON WINAPI CreateIcon( HINSTANCE hInstance, INT nWidth,
993 INT nHeight, BYTE bPlanes, BYTE bBitsPixel,
994 LPCVOID lpANDbits, LPCVOID lpXORbits )
998 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
999 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1001 info.ptHotSpot.x = 0;
1002 info.ptHotSpot.y = 0;
1003 info.nWidth = nWidth;
1004 info.nHeight = nHeight;
1005 info.nWidthBytes = 0;
1006 info.bPlanes = bPlanes;
1007 info.bBitsPerPixel = bBitsPixel;
1009 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1013 /***********************************************************************
1014 * CreateCursorIconIndirect (USER.408)
1016 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1017 CURSORICONINFO *info,
1023 int sizeAnd, sizeXor;
1025 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1026 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1027 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1028 sizeXor = info->nHeight * info->nWidthBytes;
1029 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1030 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1031 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1033 if (hInstance) FarSetOwner16( handle, hInstance );
1034 ptr = (char *)GlobalLock16( handle );
1035 memcpy( ptr, info, sizeof(*info) );
1036 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1037 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1038 GlobalUnlock16( handle );
1043 /***********************************************************************
1044 * CopyIcon16 (USER.368)
1046 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1048 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
1049 return CURSORICON_Copy( hInstance, hIcon );
1053 /***********************************************************************
1054 * CopyIcon32 (USER32.60)
1056 HICON WINAPI CopyIcon( HICON hIcon )
1058 HTASK16 hTask = GetCurrentTask ();
1059 TDB* pTask = (TDB *) GlobalLock16 (hTask);
1060 TRACE(icon, "%04x\n", hIcon );
1061 return CURSORICON_Copy( pTask->hInstance, hIcon );
1065 /***********************************************************************
1066 * CopyCursor16 (USER.369)
1068 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1070 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
1071 return CURSORICON_Copy( hInstance, hCursor );
1074 /**********************************************************************
1075 * CURSORICON_Destroy (USER.610)
1077 * This routine is actually exported from Win95 USER under the name
1078 * DestroyIcon32 ... The behaviour implemented here should mimic
1079 * the Win95 one exactly, especially the return values, which
1080 * depend on the setting of various flags.
1082 WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags )
1086 TRACE( icon, "(%04x, %04x)\n", handle, flags );
1088 /* Check whether destroying active cursor */
1090 if ( hActiveCursor == handle )
1092 ERR( cursor, "Destroying active cursor!\n" );
1096 /* Try shared cursor/icon first */
1098 if ( !(flags & CID_NONSHARED) )
1100 INT count = CURSORICON_DelSharedIcon( handle );
1103 return (flags & CID_WIN32)? TRUE : (count == 0);
1105 /* FIXME: OEM cursors/icons should be recognized */
1108 /* Now assume non-shared cursor/icon */
1110 retv = GlobalFree16( handle );
1111 return (flags & CID_RESOURCE)? retv : TRUE;
1114 /***********************************************************************
1115 * DestroyIcon16 (USER.457)
1117 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1119 return CURSORICON_Destroy( hIcon, 0 );
1122 /***********************************************************************
1123 * DestroyIcon (USER32.133)
1125 BOOL WINAPI DestroyIcon( HICON hIcon )
1127 return CURSORICON_Destroy( hIcon, CID_WIN32 );
1130 /***********************************************************************
1131 * DestroyCursor16 (USER.458)
1133 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1135 return CURSORICON_Destroy( hCursor, 0 );
1138 /***********************************************************************
1139 * DestroyCursor (USER32.132)
1141 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1143 return CURSORICON_Destroy( hCursor, CID_WIN32 );
1147 /***********************************************************************
1148 * DrawIcon16 (USER.84)
1150 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1152 return DrawIcon( hdc, x, y, hIcon );
1156 /***********************************************************************
1157 * DrawIcon32 (USER32.159)
1159 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1161 CURSORICONINFO *ptr;
1163 HBITMAP hXorBits, hAndBits;
1164 COLORREF oldFg, oldBg;
1166 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1167 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1168 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1170 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1171 ptr->bBitsPerPixel, (char *)(ptr + 1)
1172 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1173 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1174 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1176 if (hXorBits && hAndBits)
1178 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1179 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1180 SelectObject( hMemDC, hXorBits );
1181 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1182 SelectObject( hMemDC, hBitTemp );
1185 if (hXorBits) DeleteObject( hXorBits );
1186 if (hAndBits) DeleteObject( hAndBits );
1187 GlobalUnlock16( hIcon );
1188 SetTextColor( hdc, oldFg );
1189 SetBkColor( hdc, oldBg );
1194 /***********************************************************************
1195 * DumpIcon (USER.459)
1197 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1198 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1200 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1201 int sizeAnd, sizeXor;
1203 if (!info) return 0;
1204 sizeXor = info->nHeight * info->nWidthBytes;
1205 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1206 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1207 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1208 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1209 return MAKELONG( sizeXor, sizeXor );
1213 /***********************************************************************
1214 * SetCursor16 (USER.69)
1216 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1218 return (HCURSOR16)SetCursor( hCursor );
1222 /***********************************************************************
1223 * SetCursor32 (USER32.472)
1225 * A handle to the previous cursor shape.
1227 HCURSOR WINAPI SetCursor(
1228 HCURSOR hCursor /* Handle of cursor to show */
1232 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1233 TRACE(cursor, "%04x\n", hCursor );
1234 hOldCursor = hActiveCursor;
1235 hActiveCursor = hCursor;
1236 /* Change the cursor shape only if it is visible */
1237 if (CURSOR_ShowCount >= 0)
1239 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1240 GlobalUnlock16( hActiveCursor );
1246 /***********************************************************************
1247 * SetCursorPos16 (USER.70)
1249 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1251 SetCursorPos( x, y );
1255 /***********************************************************************
1256 * SetCursorPos32 (USER32.474)
1258 BOOL WINAPI SetCursorPos( INT x, INT y )
1260 DISPLAY_MoveCursor( x, y );
1265 /***********************************************************************
1266 * ShowCursor16 (USER.71)
1268 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1270 return ShowCursor( bShow );
1274 /***********************************************************************
1275 * ShowCursor32 (USER32.530)
1277 INT WINAPI ShowCursor( BOOL bShow )
1279 TRACE(cursor, "%d, count=%d\n",
1280 bShow, CURSOR_ShowCount );
1284 if (++CURSOR_ShowCount == 0) /* Show it */
1286 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1287 GlobalUnlock16( hActiveCursor );
1292 if (--CURSOR_ShowCount == -1) /* Hide it */
1293 DISPLAY_SetCursor( NULL );
1295 return CURSOR_ShowCount;
1299 /***********************************************************************
1300 * GetCursor16 (USER.247)
1302 HCURSOR16 WINAPI GetCursor16(void)
1304 return hActiveCursor;
1308 /***********************************************************************
1309 * GetCursor32 (USER32.227)
1311 HCURSOR WINAPI GetCursor(void)
1313 return hActiveCursor;
1317 /***********************************************************************
1318 * ClipCursor16 (USER.16)
1320 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1322 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1323 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1328 /***********************************************************************
1329 * ClipCursor32 (USER32.53)
1331 BOOL WINAPI ClipCursor( const RECT *rect )
1333 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1334 else CopyRect( &CURSOR_ClipRect, rect );
1339 /***********************************************************************
1340 * GetCursorPos16 (USER.17)
1342 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
1344 DWORD posX, posY, state;
1347 if (!EVENT_QueryPointer( &posX, &posY, &state ))
1353 if (state & MK_LBUTTON)
1354 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1356 MouseButtonsStates[0] = FALSE;
1357 if (state & MK_MBUTTON)
1358 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1360 MouseButtonsStates[1] = FALSE;
1361 if (state & MK_RBUTTON)
1362 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1364 MouseButtonsStates[2] = FALSE;
1366 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1371 /***********************************************************************
1372 * GetCursorPos32 (USER32.229)
1374 BOOL WINAPI GetCursorPos( POINT *pt )
1379 ret = GetCursorPos16( &pt16 );
1380 if (pt) CONV_POINT16TO32( &pt16, pt );
1381 return ((pt) ? ret : 0);
1385 /***********************************************************************
1386 * GetClipCursor16 (USER.309)
1388 void WINAPI GetClipCursor16( RECT16 *rect )
1390 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1394 /***********************************************************************
1395 * GetClipCursor32 (USER32.221)
1397 BOOL WINAPI GetClipCursor( RECT *rect )
1401 CopyRect( rect, &CURSOR_ClipRect );
1407 /**********************************************************************
1408 * LookupIconIdFromDirectoryEx16 (USER.364)
1410 * FIXME: exact parameter sizes
1412 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1413 INT16 width, INT16 height, UINT16 cFlag )
1415 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1417 if( dir && !dir->idReserved && (dir->idType & 3) )
1419 CURSORICONDIRENTRY* entry;
1424 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1427 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1432 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1434 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1436 if( entry ) retVal = entry->wResId;
1438 else WARN(cursor, "invalid resource directory\n");
1442 /**********************************************************************
1443 * LookupIconIdFromDirectoryEx32 (USER32.380)
1445 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1446 INT width, INT height, UINT cFlag )
1448 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1451 /**********************************************************************
1452 * LookupIconIdFromDirectory (USER.???)
1454 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1456 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1457 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1458 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1461 /**********************************************************************
1462 * LookupIconIdFromDirectory (USER32.379)
1464 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1466 return LookupIconIdFromDirectoryEx( dir, bIcon,
1467 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1468 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1471 /**********************************************************************
1472 * GetIconID (USER.455)
1474 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1476 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1478 TRACE(cursor, "hRes=%04x, entries=%i\n",
1479 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1484 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1485 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1487 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1488 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1490 WARN(cursor, "invalid res type %ld\n", resType );
1495 /**********************************************************************
1496 * LoadCursorIconHandler (USER.336)
1498 * Supposed to load resources of Windows 2.x applications.
1500 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1502 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1503 hResource, hModule, hRsrc);
1504 return (HGLOBAL16)0;
1507 /**********************************************************************
1508 * LoadDIBIconHandler (USER.357)
1510 * RT_ICON resource loader, installed by USER_SignalProc when module
1513 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1515 /* If hResource is zero we must allocate a new memory block, if it's
1516 * non-zero but GlobalLock() returns NULL then it was discarded and
1517 * we have to recommit some memory, otherwise we just need to check
1518 * the block size. See LoadProc() in 16-bit SDK for more.
1521 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1524 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1525 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1526 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1527 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1532 /**********************************************************************
1533 * LoadDIBCursorHandler (USER.356)
1535 * RT_CURSOR resource loader. Same as above.
1537 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1539 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1542 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1543 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1544 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1545 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1550 /**********************************************************************
1551 * LoadIconHandler (USER.456)
1553 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1555 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1557 TRACE(cursor,"hRes=%04x\n",hResource);
1559 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1560 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1563 /***********************************************************************
1564 * LoadCursorW (USER32.362)
1566 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1568 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1569 LR_SHARED | LR_DEFAULTSIZE );
1572 /***********************************************************************
1573 * LoadCursorA (USER32.359)
1575 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1577 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1578 LR_SHARED | LR_DEFAULTSIZE );
1581 /***********************************************************************
1582 * LoadCursorFromFileW (USER32.361)
1584 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1586 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1587 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1590 /***********************************************************************
1591 * LoadCursorFromFileA (USER32.360)
1593 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1595 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1596 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1599 /***********************************************************************
1600 * LoadIconW (USER32.364)
1602 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1604 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1605 LR_SHARED | LR_DEFAULTSIZE );
1608 /***********************************************************************
1609 * LoadIconA (USER32.363)
1611 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1613 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1614 LR_SHARED | LR_DEFAULTSIZE );
1617 /**********************************************************************
1618 * GetIconInfo16 (USER.395)
1620 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1623 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1625 iconinfo->fIcon = ii32.fIcon;
1626 iconinfo->xHotspot = ii32.xHotspot;
1627 iconinfo->yHotspot = ii32.yHotspot;
1628 iconinfo->hbmMask = ii32.hbmMask;
1629 iconinfo->hbmColor = ii32.hbmColor;
1633 /**********************************************************************
1634 * GetIconInfo32 (USER32.242)
1636 BOOL WINAPI GetIconInfo(HICON hIcon,LPICONINFO iconinfo) {
1637 CURSORICONINFO *ciconinfo;
1639 ciconinfo = GlobalLock16(hIcon);
1642 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1643 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1644 iconinfo->fIcon = TRUE; /* hmm */
1646 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1647 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1648 (char *)(ciconinfo + 1)
1649 + ciconinfo->nHeight *
1650 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1651 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1652 1, 1, (char *)(ciconinfo + 1));
1654 GlobalUnlock16(hIcon);
1659 /**********************************************************************
1660 * CreateIconIndirect (USER32.78)
1662 HICON WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1663 BITMAPOBJ *bmpXor,*bmpAnd;
1665 int sizeXor,sizeAnd;
1667 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1668 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1670 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1671 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1673 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1674 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1677 CURSORICONINFO *info;
1679 info = (CURSORICONINFO *)GlobalLock16( hObj );
1680 info->ptHotSpot.x = iconinfo->xHotspot;
1681 info->ptHotSpot.y = iconinfo->yHotspot;
1682 info->nWidth = bmpXor->bitmap.bmWidth;
1683 info->nHeight = bmpXor->bitmap.bmHeight;
1684 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1685 info->bPlanes = bmpXor->bitmap.bmPlanes;
1686 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1688 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1690 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1691 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1692 GlobalUnlock16( hObj );
1698 /**********************************************************************
1700 DrawIconEx16 (USER.394)
1702 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1703 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1704 HBRUSH16 hbr, UINT16 flags)
1706 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1711 /******************************************************************************
1712 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1715 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1718 * hdc [I] Handle to device context
1719 * x0 [I] X coordinate of upper left corner
1720 * y0 [I] Y coordinate of upper left corner
1721 * hIcon [I] Handle to icon to draw
1722 * cxWidth [I] Width of icon
1723 * cyWidth [I] Height of icon
1724 * istep [I] Index of frame in animated cursor
1725 * hbr [I] Handle to background brush
1726 * flags [I] Icon-drawing flags
1732 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1733 INT cxWidth, INT cyWidth, UINT istep,
1734 HBRUSH hbr, UINT flags )
1736 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1737 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1738 BOOL result = FALSE, DoOffscreen = FALSE;
1739 HBITMAP hB_off = 0, hOld = 0;
1741 if (!ptr) return FALSE;
1744 FIXME(icon, "Ignoring istep=%d\n", istep);
1745 if (flags & DI_COMPAT)
1746 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1748 /* Calculate the size of the destination image. */
1751 if (flags & DI_DEFAULTSIZE)
1752 cxWidth = GetSystemMetrics (SM_CXICON);
1754 cxWidth = ptr->nWidth;
1758 if (flags & DI_DEFAULTSIZE)
1759 cyWidth = GetSystemMetrics (SM_CYICON);
1761 cyWidth = ptr->nHeight;
1764 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1765 STOCK_HOLLOW_BRUSH)))
1767 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1770 UINT16 magic = object->wMagic;
1771 GDI_HEAP_UNLOCK(hbr);
1772 DoOffscreen = magic == BRUSH_MAGIC;
1783 hDC_off = CreateCompatibleDC(hdc);
1784 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1785 if (hDC_off && hB_off) {
1786 hOld = SelectObject(hDC_off, hB_off);
1787 FillRect(hDC_off, &r, hbr);
1791 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1793 HBITMAP hXorBits, hAndBits;
1794 COLORREF oldFg, oldBg;
1797 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1799 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1800 ptr->bPlanes, ptr->bBitsPerPixel,
1803 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1804 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1805 1, 1, (char *)(ptr+1) );
1806 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1807 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1809 if (hXorBits && hAndBits)
1811 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1812 if (flags & DI_MASK)
1815 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1816 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1818 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1819 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1821 SelectObject( hMemDC, hXorBits );
1822 if (flags & DI_IMAGE)
1825 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
1826 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1828 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
1829 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1831 SelectObject( hMemDC, hBitTemp );
1835 SetTextColor( hdc, oldFg );
1836 SetBkColor( hdc, oldBg );
1837 if (hXorBits) DeleteObject( hXorBits );
1838 if (hAndBits) DeleteObject( hAndBits );
1839 SetStretchBltMode (hdc, nStretchMode);
1841 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1842 SelectObject(hDC_off, hOld);
1845 if (hMemDC) DeleteDC( hMemDC );
1846 if (hDC_off) DeleteDC(hDC_off);
1847 if (hB_off) DeleteObject(hB_off);
1848 GlobalUnlock16( hIcon );