2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
5 * 1996 Martin Von Loewis
12 * http://www.microsoft.com/win32dev/ui/icons.htm
14 * Cursors and icons are stored in a global heap block, with the
17 * CURSORICONINFO info;
21 * The bits structures are in the format of a device-dependent bitmap.
23 * This layout is very sub-optimal, as the bitmap bits are stored in
24 * the X client instead of in the server like other bitmaps; however,
25 * some programs (notably Paint Brush) expect to be able to manipulate
26 * the bits directly :-(
37 #include "cursoricon.h"
38 #include "sysmetrics.h"
48 Cursor CURSORICON_XCursor = None; /* Current X cursor */
49 static HCURSOR32 hActiveCursor = 0; /* Active cursor */
50 static INT32 CURSOR_ShowCount = 0; /* Cursor display count */
51 static RECT32 CURSOR_ClipRect; /* Cursor clipping rect */
53 /**********************************************************************
54 * CURSORICON_FindBestIcon
56 * Find the icon closest to the requested size and number of colors.
58 static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
59 int height, int colors )
61 int i, maxcolors, maxwidth, maxheight;
62 ICONDIRENTRY *entry, *bestEntry = NULL;
66 WARN(icon, "Empty directory!\n" );
69 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
71 /* First find the exact size with less colors */
74 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
75 if ((entry->bWidth == width) && (entry->bHeight == height) &&
76 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
79 maxcolors = entry->bColorCount;
81 if (bestEntry) return bestEntry;
83 /* First find the exact size with more colors */
86 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
87 if ((entry->bWidth == width) && (entry->bHeight == height) &&
88 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
91 maxcolors = entry->bColorCount;
93 if (bestEntry) return bestEntry;
95 /* Now find a smaller one with less colors */
97 maxcolors = maxwidth = maxheight = 0;
98 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
99 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
100 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
101 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
104 maxwidth = entry->bWidth;
105 maxheight = entry->bHeight;
106 maxcolors = entry->bColorCount;
108 if (bestEntry) return bestEntry;
110 /* Now find a smaller one with more colors */
113 maxwidth = maxheight = 0;
114 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
115 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
116 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
117 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
120 maxwidth = entry->bWidth;
121 maxheight = entry->bHeight;
122 maxcolors = entry->bColorCount;
124 if (bestEntry) return bestEntry;
126 /* Now find a larger one with less colors */
129 maxwidth = maxheight = 255;
130 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
131 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
132 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
135 maxwidth = entry->bWidth;
136 maxheight = entry->bHeight;
137 maxcolors = entry->bColorCount;
139 if (bestEntry) return bestEntry;
141 /* Now find a larger one with more colors */
143 maxcolors = maxwidth = maxheight = 255;
144 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
145 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
146 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
149 maxwidth = entry->bWidth;
150 maxheight = entry->bHeight;
151 maxcolors = entry->bColorCount;
158 /**********************************************************************
159 * CURSORICON_FindBestCursor
161 * Find the cursor closest to the requested size.
163 static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
164 int width, int height )
166 int i, maxwidth, maxheight;
167 CURSORDIRENTRY *entry, *bestEntry = NULL;
169 if (dir->idCount < 1)
171 WARN(cursor, "Empty directory!\n" );
174 if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
176 /* First find the largest one smaller than or equal to the requested size*/
178 maxwidth = maxheight = 0;
179 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
180 if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
181 (entry->wWidth > maxwidth) && (entry->wHeight > maxheight))
184 maxwidth = entry->wWidth;
185 maxheight = entry->wHeight;
187 if (bestEntry) return bestEntry;
189 /* Now find the smallest one larger than the requested size */
191 maxwidth = maxheight = 255;
192 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
193 if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight))
196 maxwidth = entry->wWidth;
197 maxheight = entry->wHeight;
204 /**********************************************************************
205 * CURSORICON_LoadDirEntry16
207 * Load the icon/cursor directory for a given resource name and find the
208 * best matching entry.
210 static BOOL32 CURSORICON_LoadDirEntry16( HINSTANCE32 hInstance, SEGPTR name,
211 INT32 width, INT32 height, INT32 colors,
212 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
217 CURSORICONDIRENTRY *entry = NULL;
219 if (!(hRsrc = FindResource16( hInstance, name,
220 fCursor ? RT_GROUP_CURSOR16 : RT_GROUP_ICON16 )))
222 if (!(hMem = LoadResource16( hInstance, hRsrc ))) return FALSE;
223 if ((dir = (CURSORICONDIR *)LockResource16( hMem )))
226 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
229 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
230 width, height, colors );
231 if (entry) *dirEntry = *entry;
233 FreeResource16( hMem );
234 return (entry != NULL);
238 /**********************************************************************
239 * CURSORICON_LoadDirEntry32
241 * Load the icon/cursor directory for a given resource name and find the
242 * best matching entry.
244 static BOOL32 CURSORICON_LoadDirEntry32( HINSTANCE32 hInstance, LPCWSTR name,
245 INT32 width, INT32 height, INT32 colors,
246 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
251 CURSORICONDIRENTRY *entry = NULL;
253 if (!(hRsrc = FindResource32W( hInstance, name,
254 fCursor ? RT_GROUP_CURSOR32W : RT_GROUP_ICON32W )))
256 if (!(hMem = LoadResource32( hInstance, hRsrc ))) return FALSE;
257 if ((dir = (CURSORICONDIR*)LockResource32( hMem )))
260 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
263 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
264 width, height, colors );
265 if (entry) *dirEntry = *entry;
267 FreeResource32( hMem );
268 return (entry != NULL);
272 /**********************************************************************
273 * CURSORICON_CreateFromResource
275 * Create a cursor or icon from in-memory resource template.
277 * FIXME: Adjust icon size when width and height are nonzero (stretchblt).
278 * Convert to mono when cFlag is LR_MONOCHROME. Do something
279 * with cbSize parameter as well.
281 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
282 UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion,
283 INT32 width, INT32 height, UINT32 cFlag )
285 int sizeAnd, sizeXor;
286 HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */
287 BITMAPOBJ *bmpXor, *bmpAnd;
288 POINT16 hotspot = { 0 ,0 };
292 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
293 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
294 bIcon ? "icon" : "cursor", cFlag ? "mono" : "" );
295 if (dwVersion == 0x00020000)
297 FIXME(cursor,"\t2.xx resources are not supported\n");
302 bmi = (BITMAPINFO *)bits;
303 else /* get the hotspot */
305 POINT16 *pt = (POINT16 *)bits;
307 bmi = (BITMAPINFO *)(pt + 1);
310 /* Check bitmap header */
312 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
313 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
314 bmi->bmiHeader.biCompression != BI_RGB) )
316 WARN(cursor,"\tinvalid resource bitmap header.\n");
320 if( (hdc = GetDC32( 0 )) )
323 INT32 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
325 /* Make sure we have room for the monochrome bitmap later on.
326 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
327 * up to and including the biBitCount. In-memory icon resource
328 * format is as follows:
330 * BITMAPINFOHEADER icHeader // DIB header
331 * RGBQUAD icColors[] // Color table
332 * BYTE icXOR[] // DIB bits for XOR mask
333 * BYTE icAND[] // DIB bits for AND mask
336 if( (pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
337 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))) )
339 memcpy( pInfo, bmi, size );
340 pInfo->bmiHeader.biHeight /= 2;
342 /* Create the XOR bitmap */
344 hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
345 (char*)bmi + size, pInfo, DIB_RGB_COLORS );
348 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
349 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
350 bmi->bmiHeader.biBitCount) / 2;
352 pInfo->bmiHeader.biBitCount = 1;
353 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
355 RGBQUAD *rgb = pInfo->bmiColors;
357 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
358 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
359 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
360 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
364 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
366 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
367 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
370 /* Create the AND bitmap */
372 hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
373 bits, pInfo, DIB_RGB_COLORS );
374 if( !hAndBits ) DeleteObject32( hXorBits );
376 HeapFree( GetProcessHeap(), 0, pInfo );
378 ReleaseDC32( 0, hdc );
381 if( !hXorBits || !hAndBits )
383 WARN(cursor,"\tunable to create an icon bitmap.\n");
387 /* Now create the CURSORICONINFO structure */
389 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
390 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
391 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
392 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
394 if (hObj) hObj = GlobalReAlloc16( hObj,
395 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
396 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
397 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
400 CURSORICONINFO *info;
402 /* Make it owned by the module */
403 if (hInstance) FarSetOwner( hObj, GetExePtr(hInstance) );
405 info = (CURSORICONINFO *)GlobalLock16( hObj );
406 info->ptHotSpot.x = hotspot.x;
407 info->ptHotSpot.y = hotspot.y;
408 info->nWidth = bmpXor->bitmap.bmWidth;
409 info->nHeight = bmpXor->bitmap.bmHeight;
410 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
411 info->bPlanes = bmpXor->bitmap.bmPlanes;
412 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
414 /* Transfer the bitmap bits to the CURSORICONINFO structure */
416 GetBitmapBits32( hAndBits, sizeAnd, (char *)(info + 1) );
417 GetBitmapBits32( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
418 GlobalUnlock16( hObj );
421 DeleteObject32( hXorBits );
422 DeleteObject32( hAndBits );
427 /**********************************************************************
428 * CreateIconFromResourceEx16 (USER.450)
430 * FIXME: not sure about exact parameter types
432 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
433 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
435 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
437 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
438 width, height, cFlag );
443 /**********************************************************************
444 * CreateIconFromResource (USER32.76)
446 * bon@elektron.ikp.physik.tu-darmstadt.de 971130: Test with weditres
447 * showed only blank layout. Couldn't determine if this is a problem
448 * with CreateIconFromResource32 or the application. The application
449 * windows behaves strange (no redraw) before CreateIconFromResource32
451 HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
452 BOOL32 bIcon, DWORD dwVersion)
455 ret = CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, 0,0,0);
456 FIXME(icon,"probably only a stub\n");
457 TRACE(icon, "%s at %p size %d winver %d return 0x%04x\n",
458 (bIcon)?"Icon":"Cursor",bits,cbSize,bIcon,ret);
463 /**********************************************************************
464 * CreateIconFromResourceEx32 (USER32.77)
466 HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
467 BOOL32 bIcon, DWORD dwVersion,
468 INT32 width, INT32 height,
471 return CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, width, height, cFlag );
475 /**********************************************************************
478 * Load a cursor or icon from a 16-bit resource.
480 static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
481 INT32 width, INT32 height, INT32 colors,
486 CURSORICONDIRENTRY dirEntry;
488 if (!hInstance) /* OEM cursor/icon */
490 if (HIWORD(name)) /* Check for '#xxx' name */
492 char *ptr = PTR_SEG_TO_LIN( name );
493 if (ptr[0] != '#') return 0;
494 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
496 return OBM_LoadCursorIcon( LOWORD(name), fCursor );
499 /* Find the best entry in the directory */
501 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
502 colors, fCursor, &dirEntry ) ) return 0;
503 /* Load the resource */
505 if ( (hRsrc = FindResource16( hInstance,
506 MAKEINTRESOURCE16( dirEntry.icon.wResId ),
507 fCursor ? RT_CURSOR16 : RT_ICON16 )) )
509 /* 16-bit icon or cursor resources are processed
510 * transparently by the LoadResource16() via custom
511 * resource handlers set by SetResourceHandler().
514 if ( (handle = LoadResource16( hInstance, hRsrc )) )
520 /**********************************************************************
523 * Load a cursor or icon from a 32-bit resource.
525 static HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
526 int width, int height, int colors,
531 CURSORICONDIRENTRY dirEntry;
533 if(!hInstance) /* OEM cursor/icon */
538 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
539 if( ansi[0]=='#') /*Check for '#xxx' name */
541 resid = atoi(ansi+1);
542 HeapFree( GetProcessHeap(), 0, ansi );
546 HeapFree( GetProcessHeap(), 0, ansi );
550 else resid = LOWORD(name);
551 return OBM_LoadCursorIcon(resid, fCursor);
554 /* Find the best entry in the directory */
556 if ( !CURSORICON_LoadDirEntry32( hInstance, name, width, height,
557 colors, fCursor, &dirEntry ) ) return 0;
558 /* Load the resource */
560 if ( (hRsrc = FindResource32W( hInstance,
561 MAKEINTRESOURCE32W( dirEntry.icon.wResId ),
562 fCursor ? RT_CURSOR32W : RT_ICON32W )) )
565 if ( (handle = LoadResource32( hInstance, hRsrc )) )
567 /* Hack to keep LoadCursor/Icon32() from spawning multiple
568 * copies of the same object.
570 #define pRsrcEntry ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
571 if( !pRsrcEntry->ResourceHandle )
573 LPBYTE bits = (LPBYTE)LockResource32( handle );
574 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
575 !fCursor, 0x00030000, width, height, LR_DEFAULTCOLOR );
576 pRsrcEntry->ResourceHandle = h;
578 else h = pRsrcEntry->ResourceHandle;
587 /***********************************************************************
590 * Make a copy of a cursor or icon.
592 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
594 char *ptrOld, *ptrNew;
598 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
599 if (!(hInstance = GetExePtr( hInstance ))) return 0;
600 size = GlobalSize16( handle );
601 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
602 FarSetOwner( hNew, hInstance );
603 ptrNew = (char *)GlobalLock16( hNew );
604 memcpy( ptrNew, ptrOld, size );
605 GlobalUnlock16( handle );
606 GlobalUnlock16( hNew );
610 /***********************************************************************
611 * CURSORICON_IconToCursor
613 * Converts bitmap to mono and truncates if icon is too large (should
614 * probably do StretchBlt() instead).
616 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
619 CURSORICONINFO *pIcon = NULL;
620 HTASK16 hTask = GetCurrentTask();
621 TDB* pTask = (TDB *)GlobalLock16(hTask);
624 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
625 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
626 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
631 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
632 BYTE* psPtr, *pxbPtr = pXorBits;
633 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
639 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
640 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
642 xor_width = BITMAP_GetBitsWidth( pIcon->nWidth, bpp );
643 and_width = BITMAP_GetBitsWidth( pIcon->nWidth, 1 );
644 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
646 memset(pXorBits, 0, 128);
647 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
648 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
649 cI.nWidth = 32; cI.nHeight = 32;
650 cI.nWidthBytes = 4; /* 32x1bpp */
652 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
653 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
655 for( iy = 0; iy < maxy; iy++ )
657 unsigned shift = iy % 2;
659 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
660 (and_width > 4) ? 4 : and_width );
661 for( ix = 0; ix < maxx; ix++ )
663 if( bSemiTransparent && ((ix+shift)%2) )
665 /* set AND bit, XOR bit stays 0 */
667 pbc = pAndBits + iy * 4 + ix/8;
668 *pbc |= 0x80 >> (ix%8);
672 /* keep AND bit, set XOR bit */
674 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
675 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
676 col = COLOR_ToLogical(val);
677 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
680 *pbc |= 0x80 >> (ix%8);
688 hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
690 if( !hRet ) /* fall back on default drag cursor */
691 hRet = CURSORICON_Copy( pTask->hInstance ,
692 CURSORICON_Load16(0,MAKEINTRESOURCE16(OCR_DRAGOBJECT),
693 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE) );
700 /***********************************************************************
701 * LoadCursor16 (USER.173)
703 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
706 TRACE(cursor, "%04x '%s'\n",
707 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
709 TRACE(cursor, "%04x %04x\n",
710 hInstance, LOWORD(name) );
712 return CURSORICON_Load16( hInstance, name,
713 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
717 /***********************************************************************
718 * LoadIcon16 (USER.174)
720 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
723 TRACE(icon, "%04x '%s'\n",
724 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
726 TRACE(icon, "%04x %04x\n",
727 hInstance, LOWORD(name) );
729 return CURSORICON_Load16( hInstance, name,
730 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
731 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
735 /***********************************************************************
736 * CreateCursor16 (USER.406)
738 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
739 INT16 xHotSpot, INT16 yHotSpot,
740 INT16 nWidth, INT16 nHeight,
741 LPCVOID lpANDbits, LPCVOID lpXORbits )
743 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
745 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
746 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
747 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
751 /***********************************************************************
752 * CreateCursor32 (USER32.67)
754 HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
755 INT32 xHotSpot, INT32 yHotSpot,
756 INT32 nWidth, INT32 nHeight,
757 LPCVOID lpANDbits, LPCVOID lpXORbits )
759 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
761 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
762 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
763 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
767 /***********************************************************************
768 * CreateIcon16 (USER.407)
770 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
771 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
772 LPCVOID lpANDbits, LPCVOID lpXORbits )
774 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
776 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
777 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
778 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
782 /***********************************************************************
783 * CreateIcon32 (USER32.75)
785 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
786 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
787 LPCVOID lpANDbits, LPCVOID lpXORbits )
789 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
791 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
792 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
793 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
797 /***********************************************************************
798 * CreateCursorIconIndirect (USER.408)
800 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
801 CURSORICONINFO *info,
807 int sizeAnd, sizeXor;
809 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
810 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
811 info->nWidthBytes = BITMAP_WIDTH_BYTES(info->nWidth,info->bBitsPerPixel);
812 sizeXor = info->nHeight * info->nWidthBytes;
813 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
814 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
815 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
817 if (hInstance) FarSetOwner( handle, hInstance );
818 ptr = (char *)GlobalLock16( handle );
819 memcpy( ptr, info, sizeof(*info) );
820 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
821 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
822 GlobalUnlock16( handle );
827 /***********************************************************************
828 * CopyIcon16 (USER.368)
830 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
832 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
833 return CURSORICON_Copy( hInstance, hIcon );
837 /***********************************************************************
838 * CopyIcon32 (USER32.60)
840 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
842 HTASK16 hTask = GetCurrentTask ();
843 TDB* pTask = (TDB *) GlobalLock16 (hTask);
844 TRACE(icon, "%04x\n", hIcon );
845 return CURSORICON_Copy( pTask->hInstance, hIcon );
849 /***********************************************************************
850 * CopyCursor16 (USER.369)
852 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
854 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
855 return CURSORICON_Copy( hInstance, hCursor );
859 /***********************************************************************
860 * DestroyIcon16 (USER.457)
862 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
864 TRACE(icon, "%04x\n", hIcon );
865 /* FIXME: should check for OEM/global heap icon here */
866 return (FreeResource16( hIcon ) == 0);
870 /***********************************************************************
871 * DestroyIcon32 (USER32.133)
873 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
875 TRACE(icon, "%04x\n", hIcon );
876 /* FIXME: should check for OEM/global heap icon here */
877 /* Unlike DestroyIcon16, only icons created with CreateIcon32
878 are valid for DestroyIcon32, so don't use FreeResource32 */
879 return (GlobalFree16( hIcon ) == 0);
883 /***********************************************************************
884 * DestroyCursor16 (USER.458)
886 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
888 TRACE(cursor, "%04x\n", hCursor );
889 if (FreeResource16( hCursor ) == 0)
892 /* I believe this very same line should be added for every function
893 where appears the comment:
895 "FIXME: should check for OEM/global heap cursor here"
897 which are most (all?) the ones that call FreeResource, at least
898 in this module. Maybe this should go to a wrapper to avoid
899 repetition. Or: couldn't it go to FreeResoutce itself?
901 I'll let this to someone savvy on the subject.
903 return (GlobalFree16 (hCursor) == 0);
907 /***********************************************************************
908 * DestroyCursor32 (USER32.132)
910 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
912 TRACE(cursor, "%04x\n", hCursor );
913 /* FIXME: should check for OEM/global heap cursor here */
914 /* Unlike DestroyCursor16, only cursors created with CreateCursor32
915 are valid for DestroyCursor32, so don't use FreeResource32 */
916 return (GlobalFree16( hCursor ) == 0);
920 /***********************************************************************
921 * DrawIcon16 (USER.84)
923 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
925 return DrawIcon32( hdc, x, y, hIcon );
929 /***********************************************************************
930 * DrawIcon32 (USER32.159)
932 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
936 HBITMAP32 hXorBits, hAndBits;
937 COLORREF oldFg, oldBg;
939 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
940 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
941 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
943 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
944 ptr->bBitsPerPixel, (char *)(ptr + 1)
945 + ptr->nHeight * BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
946 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
947 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
949 if (hXorBits && hAndBits)
951 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
952 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
953 SelectObject32( hMemDC, hXorBits );
954 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
955 SelectObject32( hMemDC, hBitTemp );
957 DeleteDC32( hMemDC );
958 if (hXorBits) DeleteObject32( hXorBits );
959 if (hAndBits) DeleteObject32( hAndBits );
960 GlobalUnlock16( hIcon );
961 SetTextColor32( hdc, oldFg );
962 SetBkColor32( hdc, oldBg );
967 /***********************************************************************
968 * DumpIcon (USER.459)
970 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
971 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
973 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
974 int sizeAnd, sizeXor;
977 sizeXor = info->nHeight * info->nWidthBytes;
978 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
979 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
980 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
981 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
982 return MAKELONG( sizeXor, sizeXor );
986 /***********************************************************************
987 * CURSORICON_SetCursor
989 * Change the X cursor. Helper function for SetCursor() and ShowCursor().
990 * The Xlib critical section must be entered before calling this function.
992 static BOOL32 CURSORICON_SetCursor( HCURSOR16 hCursor )
994 Pixmap pixmapBits, pixmapMask, pixmapAll;
996 Cursor cursor = None;
998 if (!hCursor) /* Create an empty cursor */
1000 static const char data[] = { 0 };
1002 bg.red = bg.green = bg.blue = 0x0000;
1003 pixmapBits = XCreateBitmapFromData( display, rootWindow, data, 1, 1 );
1006 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
1008 XFreePixmap( display, pixmapBits );
1011 else /* Create the X cursor from the bits */
1013 CURSORICONINFO *ptr;
1016 if (!(ptr = (CURSORICONINFO*)GlobalLock16( hCursor ))) return FALSE;
1017 if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
1019 WARN(cursor, "Cursor %04x has more than 1 bpp!\n", hCursor );
1023 /* Create a pixmap and transfer all the bits to it */
1025 /* NOTE: Following hack works, but only because XFree depth
1026 * 1 images really use 1 bit/pixel (and so the same layout
1027 * as the Windows cursor data). Perhaps use a more generic
1030 pixmapAll = XCreatePixmap( display, rootWindow,
1031 ptr->nWidth, ptr->nHeight * 2, 1 );
1032 image = XCreateImage( display, DefaultVisualOfScreen(screen),
1033 1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
1034 ptr->nHeight * 2, 16, ptr->nWidthBytes);
1037 image->byte_order = MSBFirst;
1038 image->bitmap_bit_order = MSBFirst;
1039 image->bitmap_unit = 16;
1040 _XInitImageFuncPtrs(image);
1042 XPutImage( display, pixmapAll, BITMAP_monoGC, image,
1043 0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
1045 XDestroyImage( image );
1048 /* Now create the 2 pixmaps for bits and mask */
1050 pixmapBits = XCreatePixmap( display, rootWindow,
1051 ptr->nWidth, ptr->nHeight, 1 );
1052 pixmapMask = XCreatePixmap( display, rootWindow,
1053 ptr->nWidth, ptr->nHeight, 1 );
1055 /* Make sure everything went OK so far */
1057 if (pixmapBits && pixmapMask && pixmapAll)
1059 /* We have to do some magic here, as cursors are not fully
1060 * compatible between Windows and X11. Under X11, there
1061 * are only 3 possible color cursor: black, white and
1062 * masked. So we map the 4th Windows color (invert the
1063 * bits on the screen) to black. This require some boolean
1067 * Xor And Result | Bits Mask Result
1068 * 0 0 black | 0 1 background
1069 * 0 1 no change | X 0 no change
1070 * 1 0 white | 1 1 foreground
1071 * 1 1 inverted | 0 1 background
1074 * Bits = 'Xor' and not 'And'
1075 * Mask = 'Xor' or not 'And'
1077 * FIXME: apparently some servers do support 'inverted' color.
1078 * I don't know if it's correct per the X spec, but maybe
1079 * we ought to take advantage of it. -- AJ
1081 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1082 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1083 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1084 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1085 XSetFunction( display, BITMAP_monoGC, GXandReverse );
1086 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1087 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1088 XSetFunction( display, BITMAP_monoGC, GXorReverse );
1089 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1090 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1091 XSetFunction( display, BITMAP_monoGC, GXcopy );
1092 fg.red = fg.green = fg.blue = 0xffff;
1093 bg.red = bg.green = bg.blue = 0x0000;
1094 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
1095 &fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
1098 /* Now free everything */
1100 if (pixmapAll) XFreePixmap( display, pixmapAll );
1101 if (pixmapBits) XFreePixmap( display, pixmapBits );
1102 if (pixmapMask) XFreePixmap( display, pixmapMask );
1103 GlobalUnlock16( hCursor );
1106 if (cursor == None) return FALSE;
1107 if (CURSORICON_XCursor != None) XFreeCursor( display, CURSORICON_XCursor );
1108 CURSORICON_XCursor = cursor;
1110 if (rootWindow != DefaultRootWindow(display))
1112 /* Set the cursor on the desktop window */
1113 XDefineCursor( display, rootWindow, cursor );
1117 /* Set the same cursor for all top-level windows */
1118 HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD );
1121 Window win = WIN_GetXWindow( hwnd );
1122 if (win && win!=DefaultRootWindow(display))
1123 XDefineCursor( display, win, cursor );
1124 hwnd = GetWindow32( hwnd, GW_HWNDNEXT );
1131 /***********************************************************************
1132 * SetCursor16 (USER.69)
1134 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1136 return (HCURSOR16)SetCursor32( hCursor );
1140 /***********************************************************************
1141 * SetCursor32 (USER32.472)
1143 * A handle to the previous cursor shape.
1145 HCURSOR32 WINAPI SetCursor32(
1146 HCURSOR32 hCursor /* Handle of cursor to show */
1148 HCURSOR32 hOldCursor;
1150 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1151 TRACE(cursor, "%04x\n", hCursor );
1152 hOldCursor = hActiveCursor;
1153 hActiveCursor = hCursor;
1154 /* Change the cursor shape only if it is visible */
1155 if (CURSOR_ShowCount >= 0)
1157 EnterCriticalSection( &X11DRV_CritSection );
1158 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1159 LeaveCriticalSection( &X11DRV_CritSection );
1165 /***********************************************************************
1166 * SetCursorPos16 (USER.70)
1168 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1170 SetCursorPos32( x, y );
1174 /***********************************************************************
1175 * SetCursorPos32 (USER32.474)
1177 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1179 TRACE(cursor, "x=%d y=%d\n", x, y );
1180 TSXWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, x, y );
1185 /***********************************************************************
1186 * ShowCursor16 (USER.71)
1188 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1190 return ShowCursor32( bShow );
1194 /***********************************************************************
1195 * ShowCursor32 (USER32.530)
1197 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1199 TRACE(cursor, "%d, count=%d\n",
1200 bShow, CURSOR_ShowCount );
1202 EnterCriticalSection( &X11DRV_CritSection );
1205 if (++CURSOR_ShowCount == 0) /* Show it */
1206 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1210 if (--CURSOR_ShowCount == -1) /* Hide it */
1211 CALL_LARGE_STACK( CURSORICON_SetCursor, 0 );
1213 LeaveCriticalSection( &X11DRV_CritSection );
1214 return CURSOR_ShowCount;
1218 /***********************************************************************
1219 * GetCursor16 (USER.247)
1221 HCURSOR16 WINAPI GetCursor16(void)
1223 return hActiveCursor;
1227 /***********************************************************************
1228 * GetCursor32 (USER32.227)
1230 HCURSOR32 WINAPI GetCursor32(void)
1232 return hActiveCursor;
1236 /***********************************************************************
1237 * ClipCursor16 (USER.16)
1239 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1241 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1242 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1247 /***********************************************************************
1248 * ClipCursor32 (USER32.53)
1250 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1252 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1253 else CopyRect32( &CURSOR_ClipRect, rect );
1258 /***********************************************************************
1259 * GetCursorPos16 (USER.17)
1261 void WINAPI GetCursorPos16( POINT16 *pt )
1264 int rootX, rootY, childX, childY;
1265 unsigned int mousebut;
1268 if (!TSXQueryPointer( display, rootWindow, &root, &child,
1269 &rootX, &rootY, &childX, &childY, &mousebut ))
1275 if (mousebut & Button1Mask)
1276 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1278 MouseButtonsStates[0] = FALSE;
1279 if (mousebut & Button2Mask)
1280 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1282 MouseButtonsStates[1] = FALSE;
1283 if (mousebut & Button3Mask)
1284 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1286 MouseButtonsStates[2] = FALSE;
1288 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1292 /***********************************************************************
1293 * GetCursorPos32 (USER32.229)
1295 void WINAPI GetCursorPos32( POINT32 *pt )
1298 GetCursorPos16( &pt16 );
1299 if (pt) CONV_POINT16TO32( &pt16, pt );
1303 /***********************************************************************
1304 * GetClipCursor16 (USER.309)
1306 void WINAPI GetClipCursor16( RECT16 *rect )
1308 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1312 /***********************************************************************
1313 * GetClipCursor32 (USER32.221)
1315 void WINAPI GetClipCursor32( RECT32 *rect )
1317 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1320 /**********************************************************************
1321 * LookupIconIdFromDirectoryEx16 (USER.364)
1323 * FIXME: exact parameter sizes
1325 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1326 INT16 width, INT16 height, UINT16 cFlag )
1328 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1330 if( dir && !dir->idReserved && (dir->idType & 3) )
1332 int colors = (cFlag == LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
1335 ICONDIRENTRY* entry;
1336 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1337 if( entry ) retVal = entry->wResId;
1341 CURSORDIRENTRY* entry;
1342 entry = CURSORICON_FindBestCursor( dir, width, height );
1343 if( entry ) retVal = entry->wResId;
1346 else WARN(cursor, "invalid resource directory\n");
1350 /**********************************************************************
1351 * LookupIconIdFromDirectoryEx32 (USER32.380)
1353 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1354 INT32 width, INT32 height, UINT32 cFlag )
1356 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1359 /**********************************************************************
1360 * LookupIconIdFromDirectory (USER.???)
1362 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1364 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1365 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1366 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1369 /**********************************************************************
1370 * LookupIconIdFromDirectory (USER32.379)
1372 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1374 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1375 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1376 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1379 /**********************************************************************
1380 * GetIconID (USER.455)
1382 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1384 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1386 TRACE(cursor, "hRes=%04x, entries=%i\n",
1387 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1392 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1393 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1395 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1396 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1398 WARN(cursor, "invalid res type %ld\n", resType );
1403 /**********************************************************************
1404 * LoadCursorIconHandler (USER.336)
1406 * Supposed to load resources of Windows 2.x applications.
1408 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1410 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1411 hResource, hModule, hRsrc);
1412 return (HGLOBAL16)0;
1415 /**********************************************************************
1416 * LoadDIBIconHandler (USER.357)
1418 * RT_ICON resource loader, installed by USER_SignalProc when module
1421 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1423 /* If hResource is zero we must allocate a new memory block, if it's
1424 * non-zero but GlobalLock() returns NULL then it was discarded and
1425 * we have to recommit some memory, otherwise we just need to check
1426 * the block size. See LoadProc() in 16-bit SDK for more.
1429 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1432 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1433 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1434 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1435 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1440 /**********************************************************************
1441 * LoadDIBCursorHandler (USER.356)
1443 * RT_CURSOR resource loader. Same as above.
1445 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1447 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1450 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1451 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1452 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1453 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1458 /**********************************************************************
1459 * LoadIconHandler (USER.456)
1461 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1463 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1465 TRACE(cursor,"hRes=%04x\n",hResource);
1467 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1468 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1471 /***********************************************************************
1472 * LoadCursorW (USER32.362)
1474 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1476 return CURSORICON_Load32( hInstance, name,
1477 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
1480 /***********************************************************************
1481 * LoadCursorA (USER32.359)
1483 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1487 return LoadCursor32W(hInstance,(LPCWSTR)name);
1490 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1491 res = LoadCursor32W(hInstance, uni);
1492 HeapFree( GetProcessHeap(), 0, uni);
1496 /***********************************************************************
1497 * LoadCursorFromFile32W (USER32.361)
1499 HCURSOR32 WINAPI LoadCursorFromFile32W (LPCWSTR name)
1500 { FIXME(cursor, ":stub LoadCursorFromFile32W\n");
1501 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1505 /***********************************************************************
1506 * LoadCursorFromFile32A (USER32.360)
1508 HCURSOR32 WINAPI LoadCursorFromFile32A (LPCSTR name)
1509 { FIXME(cursor, ":stub LoadCursorFromFile32A %s\n", name);
1510 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1515 /***********************************************************************
1516 * LoadIconW (USER32.364)
1518 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1520 return CURSORICON_Load32( hInstance, name,
1521 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1522 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
1525 /***********************************************************************
1526 * LoadIconA (USER32.363)
1528 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1533 return LoadIcon32W(hInstance, (LPCWSTR)name);
1536 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1537 res = LoadIcon32W( hInstance, uni );
1538 HeapFree( GetProcessHeap(), 0, uni );
1543 /**********************************************************************
1544 * GetIconInfo (USER32.242)
1546 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1547 CURSORICONINFO *ciconinfo;
1549 ciconinfo = GlobalLock16(hIcon);
1552 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1553 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1554 iconinfo->fIcon = TRUE; /* hmm */
1556 iconinfo->hbmColor = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1557 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1558 (char *)(ciconinfo + 1)
1559 + ciconinfo->nHeight *
1560 BITMAP_GetBitsWidth (ciconinfo->nWidth,1) );
1561 // BITMAP_WIDTH_BYTES(ciconinfo->nWidth,1) );
1562 iconinfo->hbmMask = CreateBitmap32 ( ciconinfo->nWidth, ciconinfo->nHeight,
1563 1, 1, (char *)(ciconinfo + 1));
1565 GlobalUnlock16(hIcon);
1570 /**********************************************************************
1571 * CreateIconIndirect (USER32.78)
1573 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1574 BITMAPOBJ *bmpXor,*bmpAnd;
1576 int sizeXor,sizeAnd;
1578 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1579 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1581 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1582 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1584 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1585 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1588 CURSORICONINFO *info;
1590 info = (CURSORICONINFO *)GlobalLock16( hObj );
1591 info->ptHotSpot.x = iconinfo->xHotspot;
1592 info->ptHotSpot.y = iconinfo->yHotspot;
1593 info->nWidth = bmpXor->bitmap.bmWidth;
1594 info->nHeight = bmpXor->bitmap.bmHeight;
1595 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1596 info->bPlanes = bmpXor->bitmap.bmPlanes;
1597 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1599 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1601 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1602 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1603 GlobalUnlock16( hObj );
1609 /**********************************************************************
1610 * DrawIconEx16 (USER.394)
1612 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1613 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1614 HBRUSH16 hbr, UINT16 flags)
1616 return DrawIconEx32(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1621 /******************************************************************************
1622 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1625 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1628 * hdc [I] Handle to device context
1629 * x0 [I] X coordinate of upper left corner
1630 * y0 [I] Y coordinate of upper left corner
1631 * hIcon [I] Handle to icon to draw
1632 * cxWidth [I] Width of icon
1633 * cyWidth [I] Height of icon
1634 * istep [I] Index of frame in animated cursor
1635 * hbr [I] Handle to background brush
1636 * flags [I] Icon-drawing flags
1642 BOOL32 WINAPI DrawIconEx32( HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1643 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1644 HBRUSH32 hbr, UINT32 flags )
1646 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1647 HDC32 hMemDC = CreateCompatibleDC32 (hdc);
1648 BOOL32 result = FALSE;
1651 FIXME(icon, "Ignoring istep=%d\n", istep);
1653 FIXME(icon, "Ignoring hbr=%x\n", hbr);
1654 if (flags & DI_COMPAT)
1655 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1659 HBITMAP32 hXorBits, hAndBits;
1660 COLORREF oldFg, oldBg;
1663 /* Calculate the size of the destination image. */
1665 if (flags & DI_DEFAULTSIZE)
1666 cxWidth = GetSystemMetrics32 (SM_CXICON);
1668 cxWidth = ptr->nWidth;
1670 if (flags & DI_DEFAULTSIZE)
1671 cyWidth = GetSystemMetrics32 (SM_CYICON);
1673 cyWidth = ptr->nHeight;
1675 nStretchMode = SetStretchBltMode32 (hdc, STRETCH_DELETESCANS);
1677 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1678 ptr->bPlanes, ptr->bBitsPerPixel,
1681 BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
1682 hAndBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1683 1, 1, (char *)(ptr+1) );
1684 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1685 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1687 if (hXorBits && hAndBits)
1689 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1690 if (flags & DI_MASK)
1691 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1692 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
1693 SelectObject32( hMemDC, hXorBits );
1694 if (flags & DI_IMAGE)
1695 StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1696 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
1697 SelectObject32( hMemDC, hBitTemp );
1701 SetTextColor32( hdc, oldFg );
1702 SetBkColor32( hdc, oldBg );
1703 if (hXorBits) DeleteObject32( hXorBits );
1704 if (hAndBits) DeleteObject32( hAndBits );
1705 SetStretchBltMode32 (hdc, nStretchMode);
1707 if (hMemDC) DeleteDC32( hMemDC );
1708 GlobalUnlock16( hIcon );