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 ?!
39 #include "cursoricon.h"
40 #include "sysmetrics.h"
52 static HCURSOR32 hActiveCursor = 0; /* Active cursor */
53 static INT32 CURSOR_ShowCount = 0; /* Cursor display count */
54 static RECT32 CURSOR_ClipRect; /* Cursor clipping rect */
56 /**********************************************************************
57 * CURSORICON_FindBestIcon
59 * Find the icon closest to the requested size and number of colors.
61 static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
62 int height, int colors )
64 int i, maxcolors, maxwidth, maxheight;
65 ICONDIRENTRY *entry, *bestEntry = NULL;
69 WARN(icon, "Empty directory!\n" );
72 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
74 /* First find the exact size with less colors */
77 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
78 if ((entry->bWidth == width) && (entry->bHeight == height) &&
79 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
82 maxcolors = entry->bColorCount;
84 if (bestEntry) return bestEntry;
86 /* First find the exact size with more colors */
89 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
90 if ((entry->bWidth == width) && (entry->bHeight == height) &&
91 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
94 maxcolors = entry->bColorCount;
96 if (bestEntry) return bestEntry;
98 /* Now find a smaller one with less colors */
100 maxcolors = maxwidth = maxheight = 0;
101 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
102 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
103 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
104 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
107 maxwidth = entry->bWidth;
108 maxheight = entry->bHeight;
109 maxcolors = entry->bColorCount;
111 if (bestEntry) return bestEntry;
113 /* Now find a smaller one with more colors */
116 maxwidth = maxheight = 0;
117 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
118 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
119 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
120 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
123 maxwidth = entry->bWidth;
124 maxheight = entry->bHeight;
125 maxcolors = entry->bColorCount;
127 if (bestEntry) return bestEntry;
129 /* Now find a larger one with less colors */
132 maxwidth = maxheight = 255;
133 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
134 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
135 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
138 maxwidth = entry->bWidth;
139 maxheight = entry->bHeight;
140 maxcolors = entry->bColorCount;
142 if (bestEntry) return bestEntry;
144 /* Now find a larger one with more colors */
146 maxcolors = maxwidth = maxheight = 255;
147 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
148 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
149 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
152 maxwidth = entry->bWidth;
153 maxheight = entry->bHeight;
154 maxcolors = entry->bColorCount;
161 /**********************************************************************
162 * CURSORICON_FindBestCursor
164 * Find the cursor closest to the requested size.
165 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
168 static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
169 int width, int height, int color)
171 int i, maxwidth, maxheight;
172 CURSORDIRENTRY *entry, *bestEntry = NULL;
174 if (dir->idCount < 1)
176 WARN(cursor, "Empty directory!\n" );
179 if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
181 /* First find the largest one smaller than or equal to the requested size*/
183 maxwidth = maxheight = 0;
184 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
185 if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
186 (entry->wWidth > maxwidth) && (entry->wHeight > maxheight) &&
187 (entry->wBitCount == 1))
190 maxwidth = entry->wWidth;
191 maxheight = entry->wHeight;
193 if (bestEntry) return bestEntry;
195 /* Now find the smallest one larger than the requested size */
197 maxwidth = maxheight = 255;
198 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
199 if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight) &&
200 (entry->wBitCount == 1))
203 maxwidth = entry->wWidth;
204 maxheight = entry->wHeight;
210 /*********************************************************************
211 * The main purpose of this function is to create fake resource directory
212 * and fake resource entries. There are several reasons for this:
213 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
215 * There are some "bad" cursor files which do not have
216 * bColorCount initialized but instead one must read this info
217 * directly from corresponding DIB sections
218 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
220 BOOL32 CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL32 fCursor,
221 CURSORICONDIR **res, LPBYTE **ptr)
224 CURSORICONFILEDIR *bits;
225 int entries, size, i;
229 if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
230 if (!(entries = bits->idCount)) goto fail;
231 (int)_free = size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) *
233 for (i=0; i < entries; i++)
234 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
236 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
237 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
238 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
240 _free = (LPBYTE)(*res) + (int)_free;
241 memcpy((*res), bits, 6);
242 for (i=0; i<entries; i++)
244 ((LPBYTE*)(*ptr))[i] = _free;
246 (*res)->idEntries[i].cursor.wWidth=bits->idEntries[i].bWidth;
247 (*res)->idEntries[i].cursor.wHeight=bits->idEntries[i].bHeight;
248 (*res)->idEntries[i].cursor.wPlanes=1;
249 (*res)->idEntries[i].cursor.wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
250 bits->idEntries[i].dwDIBOffset))->biBitCount;
251 (*res)->idEntries[i].cursor.dwBytesInRes = bits->idEntries[i].dwDIBSize;
252 (*res)->idEntries[i].cursor.wResId=i+1;
253 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
254 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
255 _free+=sizeof(POINT16);
257 (*res)->idEntries[i].icon.bWidth=bits->idEntries[i].bWidth;
258 (*res)->idEntries[i].icon.bHeight=bits->idEntries[i].bHeight;
259 (*res)->idEntries[i].icon.bColorCount = bits->idEntries[i].bColorCount;
260 (*res)->idEntries[i].icon.wPlanes=1;
261 (*res)->idEntries[i].icon.wBitCount= ((LPBITMAPINFOHEADER)((LPBYTE)bits +
262 bits->idEntries[i].dwDIBOffset))->biBitCount;
263 (*res)->idEntries[i].icon.dwBytesInRes = bits->idEntries[i].dwDIBSize;
264 (*res)->idEntries[i].icon.wResId=i+1;
266 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
267 (*res)->idEntries[i].icon.dwBytesInRes);
268 _free += (*res)->idEntries[i].icon.dwBytesInRes;
270 UnmapViewOfFile( bits );
273 if (*res) HeapFree( GetProcessHeap(), 0, *res );
274 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
275 UnmapViewOfFile( bits );
279 /**********************************************************************
280 * CURSORICON_LoadDirEntry16
282 * Load the icon/cursor directory for a given resource name and find the
283 * best matching entry.
285 static BOOL32 CURSORICON_LoadDirEntry16( HINSTANCE32 hInstance, SEGPTR name,
286 INT32 width, INT32 height, INT32 colors,
287 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
292 CURSORICONDIRENTRY *entry = NULL;
294 if (!(hRsrc = FindResource16( hInstance, name,
295 fCursor ? RT_GROUP_CURSOR16 : RT_GROUP_ICON16 )))
297 if (!(hMem = LoadResource16( hInstance, hRsrc ))) return FALSE;
298 if ((dir = (CURSORICONDIR *)LockResource16( hMem )))
301 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
304 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
305 width, height, colors );
306 if (entry) *dirEntry = *entry;
308 FreeResource16( hMem );
309 return (entry != NULL);
313 /**********************************************************************
314 * CURSORICON_LoadDirEntry32
316 * Load the icon/cursor directory for a given resource name and find the
317 * best matching entry.
319 static BOOL32 CURSORICON_LoadDirEntry32( HINSTANCE32 hInstance, LPCWSTR name,
320 INT32 width, INT32 height, INT32 colors,
321 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
326 CURSORICONDIRENTRY *entry = NULL;
328 if (!(hRsrc = FindResource32W( hInstance, name,
329 fCursor ? RT_GROUP_CURSOR32W : RT_GROUP_ICON32W )))
331 if (!(hMem = LoadResource32( hInstance, hRsrc ))) return FALSE;
332 if ((dir = (CURSORICONDIR*)LockResource32( hMem )))
335 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
338 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
339 width, height, colors );
340 if (entry) *dirEntry = *entry;
342 FreeResource32( hMem );
343 return (entry != NULL);
347 /**********************************************************************
348 * CURSORICON_CreateFromResource
350 * Create a cursor or icon from in-memory resource template.
352 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
353 * with cbSize parameter as well.
355 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
356 UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion,
357 INT32 width, INT32 height, UINT32 loadflags )
359 int sizeAnd, sizeXor;
360 HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */
361 BITMAPOBJ *bmpXor, *bmpAnd;
362 POINT16 hotspot = { 0 ,0 };
368 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
369 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
370 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
371 if (dwVersion == 0x00020000)
373 FIXME(cursor,"\t2.xx resources are not supported\n");
378 bmi = (BITMAPINFO *)bits;
379 else /* get the hotspot */
381 POINT16 *pt = (POINT16 *)bits;
383 bmi = (BITMAPINFO *)(pt + 1);
385 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
387 if (!width) width = bmi->bmiHeader.biWidth;
388 if (!height) height = bmi->bmiHeader.biHeight/2;
389 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
390 (bmi->bmiHeader.biWidth != width);
392 /* Check bitmap header */
394 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
395 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
396 bmi->bmiHeader.biCompression != BI_RGB) )
398 WARN(cursor,"\tinvalid resource bitmap header.\n");
402 if( (hdc = GetDC32( 0 )) )
406 /* Make sure we have room for the monochrome bitmap later on.
407 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
408 * up to and including the biBitCount. In-memory icon resource
409 * format is as follows:
411 * BITMAPINFOHEADER icHeader // DIB header
412 * RGBQUAD icColors[] // Color table
413 * BYTE icXOR[] // DIB bits for XOR mask
414 * BYTE icAND[] // DIB bits for AND mask
417 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
418 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
420 memcpy( pInfo, bmi, size );
421 pInfo->bmiHeader.biHeight /= 2;
423 /* Create the XOR bitmap */
426 if ((hXorBits = CreateCompatibleBitmap32(hdc, width, height))) {
428 HDC32 hMem = CreateCompatibleDC32(hdc);
432 hOld = SelectObject32(hMem, hXorBits);
433 res = StretchDIBits32(hMem, 0, 0, width, height, 0, 0,
434 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
435 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
436 SelectObject32(hMem, hOld);
439 if (!res) { DeleteObject32(hXorBits); hXorBits = 0; }
441 } else hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader,
442 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
445 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
446 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
447 bmi->bmiHeader.biBitCount) / 2;
449 pInfo->bmiHeader.biBitCount = 1;
450 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
452 RGBQUAD *rgb = pInfo->bmiColors;
454 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
455 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
456 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
457 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
461 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
463 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
464 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
467 /* Create the AND bitmap */
470 if ((hAndBits = CreateBitmap32(width, height, 1, 1, NULL))) {
472 HDC32 hMem = CreateCompatibleDC32(hdc);
476 hOld = SelectObject32(hMem, hAndBits);
477 res = StretchDIBits32(hMem, 0, 0, width, height, 0, 0,
478 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
479 bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
480 SelectObject32(hMem, hOld);
483 if (!res) { DeleteObject32(hAndBits); hAndBits = 0; }
485 } else hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader,
486 CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
488 if( !hAndBits ) DeleteObject32( hXorBits );
490 HeapFree( GetProcessHeap(), 0, pInfo );
492 ReleaseDC32( 0, hdc );
495 if( !hXorBits || !hAndBits )
497 WARN(cursor,"\tunable to create an icon bitmap.\n");
501 /* Now create the CURSORICONINFO structure */
502 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
503 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
504 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
505 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
507 if (hObj) hObj = GlobalReAlloc16( hObj,
508 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
509 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
510 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
513 CURSORICONINFO *info;
515 /* Make it owned by the module */
516 if (hInstance) FarSetOwner( hObj, GetExePtr(hInstance) );
518 info = (CURSORICONINFO *)GlobalLock16( hObj );
519 info->ptHotSpot.x = hotspot.x;
520 info->ptHotSpot.y = hotspot.y;
521 info->nWidth = bmpXor->bitmap.bmWidth;
522 info->nHeight = bmpXor->bitmap.bmHeight;
523 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
524 info->bPlanes = bmpXor->bitmap.bmPlanes;
525 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
527 /* Transfer the bitmap bits to the CURSORICONINFO structure */
529 GetBitmapBits32( hAndBits, sizeAnd, (char *)(info + 1) );
530 GetBitmapBits32( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
531 GlobalUnlock16( hObj );
534 DeleteObject32( hXorBits );
535 DeleteObject32( hAndBits );
540 /**********************************************************************
541 * CreateIconFromResourceEx16 (USER.450)
543 * FIXME: not sure about exact parameter types
545 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
546 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
548 return CreateIconFromResourceEx32(bits, cbSize, bIcon, dwVersion,
549 width, height, cFlag);
553 /**********************************************************************
554 * CreateIconFromResource (USER32.76)
556 HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
557 BOOL32 bIcon, DWORD dwVersion)
559 return CreateIconFromResourceEx32( bits, cbSize, bIcon, dwVersion, 0,0,0);
563 /**********************************************************************
564 * CreateIconFromResourceEx32 (USER32.77)
566 HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
567 BOOL32 bIcon, DWORD dwVersion,
568 INT32 width, INT32 height,
571 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
573 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
574 width, height, cFlag );
579 /**********************************************************************
582 * Load a cursor or icon from a 16-bit resource.
584 static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
585 INT32 width, INT32 height, INT32 colors,
586 BOOL32 fCursor, UINT32 loadflags)
590 CURSORICONDIRENTRY dirEntry;
592 if (!hInstance) /* OEM cursor/icon */
594 if (HIWORD(name)) /* Check for '#xxx' name */
596 char *ptr = PTR_SEG_TO_LIN( name );
597 if (ptr[0] != '#') return 0;
598 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
600 return OBM_LoadCursorIcon( LOWORD(name), fCursor );
603 /* Find the best entry in the directory */
605 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
606 colors, fCursor, &dirEntry ) ) return 0;
607 /* Load the resource */
609 if ( (hRsrc = FindResource16( hInstance,
610 MAKEINTRESOURCE16( dirEntry.icon.wResId ),
611 fCursor ? RT_CURSOR16 : RT_ICON16 )) )
613 /* 16-bit icon or cursor resources are processed
614 * transparently by the LoadResource16() via custom
615 * resource handlers set by SetResourceHandler().
618 if ( (handle = LoadResource16( hInstance, hRsrc )) )
624 /**********************************************************************
627 * Load a cursor or icon from a 32-bit resource.
629 HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
630 int width, int height, int colors,
631 BOOL32 fCursor, UINT32 loadflags )
633 HANDLE32 handle, h = 0;
635 CURSORICONDIRENTRY dirEntry;
638 if (!(loadflags & LR_LOADFROMFILE))
640 if (!hInstance) /* OEM cursor/icon */
645 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
646 if( ansi[0]=='#') /*Check for '#xxx' name */
648 resid = atoi(ansi+1);
649 HeapFree( GetProcessHeap(), 0, ansi );
653 HeapFree( GetProcessHeap(), 0, ansi );
657 else resid = LOWORD(name);
658 return OBM_LoadCursorIcon(resid, fCursor);
661 /* Find the best entry in the directory */
663 if (!CURSORICON_LoadDirEntry32( hInstance, name, width, height,
664 colors, fCursor, &dirEntry ) ) return 0;
665 /* Load the resource */
667 if (!(hRsrc = FindResource32W(hInstance,MAKEINTRESOURCE32W(dirEntry.icon.wResId),
668 fCursor ? RT_CURSOR32W : RT_ICON32W ))) return 0;
669 if (!(handle = LoadResource32( hInstance, hRsrc ))) return 0;
670 /* Hack to keep LoadCursor/Icon32() from spawning multiple
671 * copies of the same object.
673 #define pRsrcEntry ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
674 if( pRsrcEntry->ResourceHandle ) return pRsrcEntry->ResourceHandle;
675 bits = (LPBYTE)LockResource32( handle );
676 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
677 !fCursor, 0x00030000, width, height, loadflags);
678 pRsrcEntry->ResourceHandle = h;
684 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &res, &ptr))
687 dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(res, width, height, 1);
689 dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(res, width, height, colors);
690 bits = ptr[dirEntry.icon.wResId-1];
691 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
692 !fCursor, 0x00030000, width, height, loadflags);
693 HeapFree( GetProcessHeap(), 0, res );
694 HeapFree( GetProcessHeap(), 0, ptr );
701 /***********************************************************************
704 * Make a copy of a cursor or icon.
706 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
708 char *ptrOld, *ptrNew;
712 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
713 if (!(hInstance = GetExePtr( hInstance ))) return 0;
714 size = GlobalSize16( handle );
715 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
716 FarSetOwner( hNew, hInstance );
717 ptrNew = (char *)GlobalLock16( hNew );
718 memcpy( ptrNew, ptrOld, size );
719 GlobalUnlock16( handle );
720 GlobalUnlock16( hNew );
724 /***********************************************************************
725 * CURSORICON_IconToCursor
727 * Converts bitmap to mono and truncates if icon is too large (should
728 * probably do StretchBlt() instead).
730 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
733 CURSORICONINFO *pIcon = NULL;
734 HTASK16 hTask = GetCurrentTask();
735 TDB* pTask = (TDB *)GlobalLock16(hTask);
738 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
739 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
740 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
745 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
746 BYTE* psPtr, *pxbPtr = pXorBits;
747 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
753 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
754 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
756 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
757 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
758 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
760 memset(pXorBits, 0, 128);
761 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
762 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
763 cI.nWidth = 32; cI.nHeight = 32;
764 cI.nWidthBytes = 4; /* 32x1bpp */
766 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
767 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
769 for( iy = 0; iy < maxy; iy++ )
771 unsigned shift = iy % 2;
773 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
774 (and_width > 4) ? 4 : and_width );
775 for( ix = 0; ix < maxx; ix++ )
777 if( bSemiTransparent && ((ix+shift)%2) )
779 /* set AND bit, XOR bit stays 0 */
781 pbc = pAndBits + iy * 4 + ix/8;
782 *pbc |= 0x80 >> (ix%8);
786 /* keep AND bit, set XOR bit */
788 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
789 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
790 col = COLOR_ToLogical(val);
791 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
794 *pbc |= 0x80 >> (ix%8);
802 hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
804 if( !hRet ) /* fall back on default drag cursor */
805 hRet = CURSORICON_Copy( pTask->hInstance ,
806 CURSORICON_Load16(0,MAKEINTRESOURCE16(OCR_DRAGOBJECT),
807 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
814 /***********************************************************************
815 * LoadCursor16 (USER.173)
817 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
820 TRACE(cursor, "%04x '%s'\n",
821 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
823 TRACE(cursor, "%04x %04x\n",
824 hInstance, LOWORD(name) );
826 return CURSORICON_Load16( hInstance, name,
827 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
831 /***********************************************************************
832 * LoadIcon16 (USER.174)
834 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
837 TRACE(icon, "%04x '%s'\n",
838 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
840 TRACE(icon, "%04x %04x\n",
841 hInstance, LOWORD(name) );
843 return CURSORICON_Load16( hInstance, name,
844 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
845 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE, 0);
849 /***********************************************************************
850 * CreateCursor16 (USER.406)
852 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
853 INT16 xHotSpot, INT16 yHotSpot,
854 INT16 nWidth, INT16 nHeight,
855 LPCVOID lpANDbits, LPCVOID lpXORbits )
857 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
859 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
860 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
861 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
865 /***********************************************************************
866 * CreateCursor32 (USER32.67)
868 HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
869 INT32 xHotSpot, INT32 yHotSpot,
870 INT32 nWidth, INT32 nHeight,
871 LPCVOID lpANDbits, LPCVOID lpXORbits )
873 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
875 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
876 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
877 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
881 /***********************************************************************
882 * CreateIcon16 (USER.407)
884 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
885 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
886 LPCVOID lpANDbits, LPCVOID lpXORbits )
888 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
890 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
891 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
892 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
896 /***********************************************************************
897 * CreateIcon32 (USER32.75)
899 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
900 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
901 LPCVOID lpANDbits, LPCVOID lpXORbits )
903 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
905 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
906 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
907 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
911 /***********************************************************************
912 * CreateCursorIconIndirect (USER.408)
914 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
915 CURSORICONINFO *info,
921 int sizeAnd, sizeXor;
923 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
924 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
925 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
926 sizeXor = info->nHeight * info->nWidthBytes;
927 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
928 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
929 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
931 if (hInstance) FarSetOwner( handle, hInstance );
932 ptr = (char *)GlobalLock16( handle );
933 memcpy( ptr, info, sizeof(*info) );
934 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
935 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
936 GlobalUnlock16( handle );
941 /***********************************************************************
942 * CopyIcon16 (USER.368)
944 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
946 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
947 return CURSORICON_Copy( hInstance, hIcon );
951 /***********************************************************************
952 * CopyIcon32 (USER32.60)
954 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
956 HTASK16 hTask = GetCurrentTask ();
957 TDB* pTask = (TDB *) GlobalLock16 (hTask);
958 TRACE(icon, "%04x\n", hIcon );
959 return CURSORICON_Copy( pTask->hInstance, hIcon );
963 /***********************************************************************
964 * CopyCursor16 (USER.369)
966 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
968 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
969 return CURSORICON_Copy( hInstance, hCursor );
973 /***********************************************************************
974 * DestroyIcon16 (USER.457)
976 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
978 TRACE(icon, "%04x\n", hIcon );
979 /* FIXME: should check for OEM/global heap icon here */
980 return (FreeResource16( hIcon ) == 0);
984 /***********************************************************************
985 * DestroyIcon32 (USER32.133)
987 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
989 TRACE(icon, "%04x\n", hIcon );
990 /* FIXME: should check for OEM/global heap icon here */
991 /* Unlike DestroyIcon16, only icons created with CreateIcon32
992 are valid for DestroyIcon32, so don't use FreeResource32 */
993 return (GlobalFree16( hIcon ) == 0);
997 /***********************************************************************
998 * DestroyCursor16 (USER.458)
1000 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1002 TRACE(cursor, "%04x\n", hCursor );
1003 if (FreeResource16( hCursor ) == 0)
1006 /* I believe this very same line should be added for every function
1007 where appears the comment:
1009 "FIXME: should check for OEM/global heap cursor here"
1011 which are most (all?) the ones that call FreeResource, at least
1012 in this module. Maybe this should go to a wrapper to avoid
1013 repetition. Or: couldn't it go to FreeResoutce itself?
1015 I'll let this to someone savvy on the subject.
1017 return (GlobalFree16 (hCursor) == 0);
1021 /***********************************************************************
1022 * DestroyCursor32 (USER32.132)
1024 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
1026 TRACE(cursor, "%04x\n", hCursor );
1027 /* FIXME: should check for OEM/global heap cursor here */
1028 /* Unlike DestroyCursor16, only cursors created with CreateCursor32
1029 are valid for DestroyCursor32, so don't use FreeResource32 */
1030 return (GlobalFree16( hCursor ) == 0);
1034 /***********************************************************************
1035 * DrawIcon16 (USER.84)
1037 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1039 return DrawIcon32( hdc, x, y, hIcon );
1043 /***********************************************************************
1044 * DrawIcon32 (USER32.159)
1046 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
1048 CURSORICONINFO *ptr;
1050 HBITMAP32 hXorBits, hAndBits;
1051 COLORREF oldFg, oldBg;
1053 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1054 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
1055 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
1057 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1058 ptr->bBitsPerPixel, (char *)(ptr + 1)
1059 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1060 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1061 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1063 if (hXorBits && hAndBits)
1065 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1066 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1067 SelectObject32( hMemDC, hXorBits );
1068 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1069 SelectObject32( hMemDC, hBitTemp );
1071 DeleteDC32( hMemDC );
1072 if (hXorBits) DeleteObject32( hXorBits );
1073 if (hAndBits) DeleteObject32( hAndBits );
1074 GlobalUnlock16( hIcon );
1075 SetTextColor32( hdc, oldFg );
1076 SetBkColor32( hdc, oldBg );
1081 /***********************************************************************
1082 * DumpIcon (USER.459)
1084 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
1085 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1087 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
1088 int sizeAnd, sizeXor;
1090 if (!info) return 0;
1091 sizeXor = info->nHeight * info->nWidthBytes;
1092 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1093 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1094 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1095 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1096 return MAKELONG( sizeXor, sizeXor );
1100 /***********************************************************************
1101 * SetCursor16 (USER.69)
1103 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1105 return (HCURSOR16)SetCursor32( hCursor );
1109 /***********************************************************************
1110 * SetCursor32 (USER32.472)
1112 * A handle to the previous cursor shape.
1114 HCURSOR32 WINAPI SetCursor32(
1115 HCURSOR32 hCursor /* Handle of cursor to show */
1117 HCURSOR32 hOldCursor;
1119 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1120 TRACE(cursor, "%04x\n", hCursor );
1121 hOldCursor = hActiveCursor;
1122 hActiveCursor = hCursor;
1123 /* Change the cursor shape only if it is visible */
1124 if (CURSOR_ShowCount >= 0)
1126 DISPLAY_SetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1127 GlobalUnlock16( hActiveCursor );
1133 /***********************************************************************
1134 * SetCursorPos16 (USER.70)
1136 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1138 SetCursorPos32( x, y );
1142 /***********************************************************************
1143 * SetCursorPos32 (USER32.474)
1145 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1147 DISPLAY_MoveCursor( x, y );
1152 /***********************************************************************
1153 * ShowCursor16 (USER.71)
1155 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1157 return ShowCursor32( bShow );
1161 /***********************************************************************
1162 * ShowCursor32 (USER32.530)
1164 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1166 TRACE(cursor, "%d, count=%d\n",
1167 bShow, CURSOR_ShowCount );
1171 if (++CURSOR_ShowCount == 0) /* Show it */
1173 DISPLAY_SetCursor((CURSORICONINFO*)GlobalLock16( hActiveCursor ));
1174 GlobalUnlock16( hActiveCursor );
1179 if (--CURSOR_ShowCount == -1) /* Hide it */
1180 DISPLAY_SetCursor( NULL );
1182 return CURSOR_ShowCount;
1186 /***********************************************************************
1187 * GetCursor16 (USER.247)
1189 HCURSOR16 WINAPI GetCursor16(void)
1191 return hActiveCursor;
1195 /***********************************************************************
1196 * GetCursor32 (USER32.227)
1198 HCURSOR32 WINAPI GetCursor32(void)
1200 return hActiveCursor;
1204 /***********************************************************************
1205 * ClipCursor16 (USER.16)
1207 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1209 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1210 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1215 /***********************************************************************
1216 * ClipCursor32 (USER32.53)
1218 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1220 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1221 else CopyRect32( &CURSOR_ClipRect, rect );
1226 /***********************************************************************
1227 * GetCursorPos16 (USER.17)
1229 void WINAPI GetCursorPos16( POINT16 *pt )
1231 DWORD posX, posY, state;
1234 if (!EVENT_QueryPointer( &posX, &posY, &state ))
1240 if (state & MK_LBUTTON)
1241 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1243 MouseButtonsStates[0] = FALSE;
1244 if (state & MK_MBUTTON)
1245 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1247 MouseButtonsStates[1] = FALSE;
1248 if (state & MK_RBUTTON)
1249 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1251 MouseButtonsStates[2] = FALSE;
1253 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1257 /***********************************************************************
1258 * GetCursorPos32 (USER32.229)
1260 void WINAPI GetCursorPos32( POINT32 *pt )
1263 GetCursorPos16( &pt16 );
1264 if (pt) CONV_POINT16TO32( &pt16, pt );
1268 /***********************************************************************
1269 * GetClipCursor16 (USER.309)
1271 void WINAPI GetClipCursor16( RECT16 *rect )
1273 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1277 /***********************************************************************
1278 * GetClipCursor32 (USER32.221)
1280 void WINAPI GetClipCursor32( RECT32 *rect )
1282 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1285 /**********************************************************************
1286 * LookupIconIdFromDirectoryEx16 (USER.364)
1288 * FIXME: exact parameter sizes
1290 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1291 INT16 width, INT16 height, UINT16 cFlag )
1293 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1295 if( dir && !dir->idReserved && (dir->idType & 3) )
1297 int colors = (cFlag & LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
1300 ICONDIRENTRY* entry;
1301 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1302 if( entry ) retVal = entry->wResId;
1306 CURSORDIRENTRY* entry;
1307 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1308 if( entry ) retVal = entry->wResId;
1311 else WARN(cursor, "invalid resource directory\n");
1315 /**********************************************************************
1316 * LookupIconIdFromDirectoryEx32 (USER32.380)
1318 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1319 INT32 width, INT32 height, UINT32 cFlag )
1321 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1324 /**********************************************************************
1325 * LookupIconIdFromDirectory (USER.???)
1327 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1329 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1330 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1331 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1334 /**********************************************************************
1335 * LookupIconIdFromDirectory (USER32.379)
1337 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1339 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1340 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1341 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1344 /**********************************************************************
1345 * GetIconID (USER.455)
1347 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1349 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1351 TRACE(cursor, "hRes=%04x, entries=%i\n",
1352 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1357 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1358 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1360 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1361 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1363 WARN(cursor, "invalid res type %ld\n", resType );
1368 /**********************************************************************
1369 * LoadCursorIconHandler (USER.336)
1371 * Supposed to load resources of Windows 2.x applications.
1373 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1375 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1376 hResource, hModule, hRsrc);
1377 return (HGLOBAL16)0;
1380 /**********************************************************************
1381 * LoadDIBIconHandler (USER.357)
1383 * RT_ICON resource loader, installed by USER_SignalProc when module
1386 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1388 /* If hResource is zero we must allocate a new memory block, if it's
1389 * non-zero but GlobalLock() returns NULL then it was discarded and
1390 * we have to recommit some memory, otherwise we just need to check
1391 * the block size. See LoadProc() in 16-bit SDK for more.
1394 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1397 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1398 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1399 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1400 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1405 /**********************************************************************
1406 * LoadDIBCursorHandler (USER.356)
1408 * RT_CURSOR resource loader. Same as above.
1410 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1412 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1415 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1416 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1417 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1418 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1423 /**********************************************************************
1424 * LoadIconHandler (USER.456)
1426 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1428 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1430 TRACE(cursor,"hRes=%04x\n",hResource);
1432 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1433 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1436 /***********************************************************************
1437 * LoadCursorW (USER32.362)
1439 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1441 return CURSORICON_Load32( hInstance, name,
1442 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
1445 /***********************************************************************
1446 * LoadCursorA (USER32.359)
1448 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1452 return LoadCursor32W(hInstance,(LPCWSTR)name);
1455 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1456 res = LoadCursor32W(hInstance, uni);
1457 HeapFree( GetProcessHeap(), 0, uni);
1461 /***********************************************************************
1462 * LoadCursorFromFile32W (USER32.361)
1464 HCURSOR32 WINAPI LoadCursorFromFile32W (LPCWSTR name)
1466 return LoadImage32W(0, name, IMAGE_CURSOR, SYSMETRICS_CXCURSOR,
1467 SYSMETRICS_CYCURSOR, LR_LOADFROMFILE);
1470 /***********************************************************************
1471 * LoadCursorFromFile32A (USER32.360)
1473 HCURSOR32 WINAPI LoadCursorFromFile32A (LPCSTR name)
1476 LPWSTR u_name = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1477 hcur = LoadCursorFromFile32W(u_name);
1478 HeapFree( GetProcessHeap(), 0, u_name );
1482 /***********************************************************************
1483 * LoadIconW (USER32.364)
1485 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1487 return CURSORICON_Load32( hInstance, name,
1488 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1489 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE, 0);
1492 /***********************************************************************
1493 * LoadIconA (USER32.363)
1495 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1500 return LoadIcon32W(hInstance, (LPCWSTR)name);
1503 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1504 res = LoadIcon32W( hInstance, uni );
1505 HeapFree( GetProcessHeap(), 0, uni );
1510 /**********************************************************************
1511 * GetIconInfo (USER32.242)
1513 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1514 CURSORICONINFO *ciconinfo;
1516 ciconinfo = GlobalLock16(hIcon);
1519 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1520 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1521 iconinfo->fIcon = TRUE; /* hmm */
1523 iconinfo->hbmColor = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1524 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1525 (char *)(ciconinfo + 1)
1526 + ciconinfo->nHeight *
1527 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1528 iconinfo->hbmMask = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1529 1, 1, (char *)(ciconinfo + 1));
1531 GlobalUnlock16(hIcon);
1536 /**********************************************************************
1537 * CreateIconIndirect (USER32.78)
1539 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1540 BITMAPOBJ *bmpXor,*bmpAnd;
1542 int sizeXor,sizeAnd;
1544 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1545 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1547 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1548 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1550 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1551 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1554 CURSORICONINFO *info;
1556 info = (CURSORICONINFO *)GlobalLock16( hObj );
1557 info->ptHotSpot.x = iconinfo->xHotspot;
1558 info->ptHotSpot.y = iconinfo->yHotspot;
1559 info->nWidth = bmpXor->bitmap.bmWidth;
1560 info->nHeight = bmpXor->bitmap.bmHeight;
1561 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1562 info->bPlanes = bmpXor->bitmap.bmPlanes;
1563 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1565 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1567 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1568 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1569 GlobalUnlock16( hObj );
1575 /**********************************************************************
1577 DrawIconEx16 (USER.394)
1579 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1580 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1581 HBRUSH16 hbr, UINT16 flags)
1583 return DrawIconEx32(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1588 /******************************************************************************
1589 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1592 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1595 * hdc [I] Handle to device context
1596 * x0 [I] X coordinate of upper left corner
1597 * y0 [I] Y coordinate of upper left corner
1598 * hIcon [I] Handle to icon to draw
1599 * cxWidth [I] Width of icon
1600 * cyWidth [I] Height of icon
1601 * istep [I] Index of frame in animated cursor
1602 * hbr [I] Handle to background brush
1603 * flags [I] Icon-drawing flags
1609 BOOL32 WINAPI DrawIconEx32( HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1610 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1611 HBRUSH32 hbr, UINT32 flags )
1613 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1614 HDC32 hDC_off = 0, hMemDC = CreateCompatibleDC32 (hdc);
1615 BOOL32 result = FALSE, DoOffscreen = FALSE;
1616 HBITMAP32 hB_off = 0, hOld = 0;
1618 if (!ptr) return FALSE;
1621 FIXME(icon, "Ignoring istep=%d\n", istep);
1622 if (flags & DI_COMPAT)
1623 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1625 /* Calculate the size of the destination image. */
1628 if (flags & DI_DEFAULTSIZE)
1629 cxWidth = GetSystemMetrics32 (SM_CXICON);
1631 cxWidth = ptr->nWidth;
1635 if (flags & DI_DEFAULTSIZE)
1636 cyWidth = GetSystemMetrics32 (SM_CYICON);
1638 cyWidth = ptr->nHeight;
1641 if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
1642 STOCK_HOLLOW_BRUSH)))
1644 GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
1647 UINT16 magic = object->wMagic;
1648 GDI_HEAP_UNLOCK(hbr);
1649 DoOffscreen = magic == BRUSH_MAGIC;
1653 RECT32 r = {0, 0, cxWidth, cxWidth};
1655 hDC_off = CreateCompatibleDC32(hdc);
1656 hB_off = CreateCompatibleBitmap32(hdc, cxWidth, cyWidth);
1657 if (hDC_off && hB_off) {
1658 hOld = SelectObject32(hDC_off, hB_off);
1659 FillRect32(hDC_off, &r, hbr);
1663 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1665 HBITMAP32 hXorBits, hAndBits;
1666 COLORREF oldFg, oldBg;
1669 nStretchMode = SetStretchBltMode32 (hdc, STRETCH_DELETESCANS);
1671 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1672 ptr->bPlanes, ptr->bBitsPerPixel,
1675 BITMAP_GetWidthBytes(ptr->nWidth,1) );
1676 hAndBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1677 1, 1, (char *)(ptr+1) );
1678 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1679 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1681 if (hXorBits && hAndBits)
1683 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1684 if (flags & DI_MASK)
1687 StretchBlt32 (hDC_off, 0, 0, cxWidth, cyWidth,
1688 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1690 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1691 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1693 SelectObject32( hMemDC, hXorBits );
1694 if (flags & DI_IMAGE)
1697 StretchBlt32 (hDC_off, 0, 0, cxWidth, cyWidth,
1698 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1700 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1701 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1703 SelectObject32( hMemDC, hBitTemp );
1707 SetTextColor32( hdc, oldFg );
1708 SetBkColor32( hdc, oldBg );
1709 if (hXorBits) DeleteObject32( hXorBits );
1710 if (hAndBits) DeleteObject32( hAndBits );
1711 SetStretchBltMode32 (hdc, nStretchMode);
1713 BitBlt32(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
1714 SelectObject32(hDC_off, hOld);
1717 if (hMemDC) DeleteDC32( hMemDC );
1718 if (hDC_off) DeleteDC32(hDC_off);
1719 if (hB_off) DeleteObject32(hB_off);
1720 GlobalUnlock16( hIcon );