Release 971012
[wine/multimedia.git] / objects / cursoricon.c
blobfb021096f4e62c7ac34ac05022d1f6bd895ee838
1 /*
2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
5 * 1996 Martin Von Loewis
6 * 1997 Alex Korobka
7 */
9 /*
10 * Theory:
12 * http://www.microsoft.com/win32dev/ui/icons.htm
14 * Cursors and icons are stored in a global heap block, with the
15 * following layout:
17 * CURSORICONINFO info;
18 * BYTE[] ANDbits;
19 * BYTE[] XORbits;
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 :-(
29 #include <string.h>
30 #include <stdlib.h>
31 #include "heap.h"
32 #include "windows.h"
33 #include "peexe.h"
34 #include "color.h"
35 #include "bitmap.h"
36 #include "callback.h"
37 #include "cursoricon.h"
38 #include "sysmetrics.h"
39 #include "module.h"
40 #include "win.h"
41 #include "stddebug.h"
42 #include "debug.h"
43 #include "task.h"
45 extern UINT16 COLOR_GetSystemPaletteSize();
46 extern HGLOBAL16 USER_CallDefaultRsrcHandler( HGLOBAL16, HMODULE16, HRSRC16 );
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;
64 if (dir->idCount < 1)
66 fprintf( stderr, "Icon: empty directory!\n" );
67 return NULL;
69 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
71 /* First find the exact size with less colors */
73 maxcolors = 0;
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))
78 bestEntry = entry;
79 maxcolors = entry->bColorCount;
81 if (bestEntry) return bestEntry;
83 /* First find the exact size with more colors */
85 maxcolors = 255;
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))
90 bestEntry = entry;
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))
103 bestEntry = entry;
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 */
112 maxcolors = 255;
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))
119 bestEntry = entry;
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 */
128 maxcolors = 0;
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))
134 bestEntry = entry;
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))
148 bestEntry = entry;
149 maxwidth = entry->bWidth;
150 maxheight = entry->bHeight;
151 maxcolors = entry->bColorCount;
154 return bestEntry;
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 fprintf( stderr, "Cursor: empty directory!\n" );
172 return NULL;
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))
183 bestEntry = entry;
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))
195 bestEntry = entry;
196 maxwidth = entry->wWidth;
197 maxheight = entry->wHeight;
200 return bestEntry;
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 )
214 HRSRC16 hRsrc;
215 HGLOBAL16 hMem;
216 CURSORICONDIR *dir;
217 CURSORICONDIRENTRY *entry = NULL;
219 if (!(hRsrc = FindResource16( hInstance, name,
220 fCursor ? RT_GROUP_CURSOR : RT_GROUP_ICON )))
221 return FALSE;
222 if (!(hMem = LoadResource16( hInstance, hRsrc ))) return FALSE;
223 if ((dir = (CURSORICONDIR *)LockResource16( hMem )))
225 if (fCursor)
226 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
227 width, height );
228 else
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 )
248 HANDLE32 hRsrc;
249 HANDLE32 hMem;
250 CURSORICONDIR *dir;
251 CURSORICONDIRENTRY *entry = NULL;
253 if (!(hRsrc = FindResource32W( hInstance, name,
254 (LPCWSTR)(fCursor ? RT_GROUP_CURSOR : RT_GROUP_ICON) )))
255 return FALSE;
256 if (!(hMem = LoadResource32( hInstance, hRsrc ))) return FALSE;
257 if ((dir = (CURSORICONDIR*)LockResource32( hMem )))
259 if (fCursor)
260 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
261 width, height );
262 else
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( HINSTANCE32 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 };
289 BITMAPINFO *bmi;
290 HDC32 hdc;
292 dprintf_cursor(stddeb,"CreateFromResource: %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 fprintf(stdnimp,"\t2.xx resources are not supported\n");
298 return 0;
301 if (bIcon)
302 bmi = (BITMAPINFO *)bits;
303 else /* get the hotspot */
305 POINT16 *pt = (POINT16 *)bits;
306 hotspot = *pt;
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 fprintf(stderr,"\tinvalid resource bitmap header.\n");
317 return 0;
320 if( (hdc = GetDC32( 0 )) )
322 BITMAPINFO* pInfo;
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 );
346 if( hXorBits )
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;
362 else
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 fprintf(stderr,"\tunable to create an icon bitmap.\n");
384 return 0;
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 );
398 if (hObj)
400 CURSORICONINFO *info;
402 /* Make it owned by the module */
403 if (hInstance) FarSetOwner( hObj, MODULE_HANDLEtoHMODULE16(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 );
423 return hObj;
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() );
436 if( pTask )
437 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
438 width, height, cFlag );
439 return 0;
443 /**********************************************************************
444 * CreateIconFromResourceEx32 (USER32.76)
446 HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
447 BOOL32 bIcon, DWORD dwVersion,
448 INT32 width, INT32 height,
449 UINT32 cFlag )
451 return CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, width, height, cFlag );
455 /**********************************************************************
456 * CURSORICON_Load16
458 * Load a cursor or icon from a 16-bit resource.
460 static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
461 INT32 width, INT32 height, INT32 colors,
462 BOOL32 fCursor )
464 HGLOBAL16 handle;
465 HRSRC16 hRsrc;
466 CURSORICONDIRENTRY dirEntry;
468 if (!hInstance) /* OEM cursor/icon */
470 if (HIWORD(name)) /* Check for '#xxx' name */
472 char *ptr = PTR_SEG_TO_LIN( name );
473 if (ptr[0] != '#') return 0;
474 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
476 return OBM_LoadCursorIcon( LOWORD(name), fCursor );
479 /* Find the best entry in the directory */
481 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
482 colors, fCursor, &dirEntry ) ) return 0;
483 /* Load the resource */
485 if ( (hRsrc = FindResource16( hInstance,
486 MAKEINTRESOURCE( dirEntry.icon.wResId ),
487 fCursor ? RT_CURSOR : RT_ICON )) )
489 /* 16-bit icon or cursor resources are processed
490 * transparently by the LoadResource16() via custom
491 * resource handlers set by SetResourceHandler().
494 if ( (handle = LoadResource16( hInstance, hRsrc )) )
495 return handle;
497 return 0;
500 /**********************************************************************
501 * CURSORICON_Load32
503 * Load a cursor or icon from a 32-bit resource.
505 static HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
506 int width, int height, int colors,
507 BOOL32 fCursor )
509 HANDLE32 handle;
510 HANDLE32 hRsrc;
511 CURSORICONDIRENTRY dirEntry;
513 if(!hInstance) /* OEM cursor/icon */
515 WORD resid;
516 if(HIWORD(name))
518 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
519 if( ansi[0]=='#') /*Check for '#xxx' name */
521 resid = atoi(ansi+1);
522 HeapFree( GetProcessHeap(), 0, ansi );
524 else
526 HeapFree( GetProcessHeap(), 0, ansi );
527 return 0;
530 else resid = LOWORD(name);
531 return OBM_LoadCursorIcon(resid, fCursor);
534 /* Find the best entry in the directory */
536 if ( !CURSORICON_LoadDirEntry32( hInstance, name, width, height,
537 colors, fCursor, &dirEntry ) ) return 0;
538 /* Load the resource */
540 if ( (hRsrc = FindResource32W( hInstance,
541 (LPWSTR) (DWORD) dirEntry.icon.wResId,
542 (LPWSTR) (fCursor ? RT_CURSOR : RT_ICON ))) )
544 HANDLE32 h = 0;
545 if ( (handle = LoadResource32( hInstance, hRsrc )) )
547 /* Hack to keep LoadCursor/Icon32() from spawning multiple
548 * copies of the same object.
550 #define pRsrcEntry ((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
551 if( !pRsrcEntry->ResourceHandle )
553 LPBYTE bits = (LPBYTE)LockResource32( handle );
554 h = CURSORICON_CreateFromResource( hInstance, 0, bits, dirEntry.icon.dwBytesInRes,
555 !fCursor, 0x00030000, width, height, LR_DEFAULTCOLOR );
556 pRsrcEntry->ResourceHandle = h;
558 else h = pRsrcEntry->ResourceHandle;
559 #undef pRsrcEntry
561 return h;
563 return 0;
567 /***********************************************************************
568 * CURSORICON_Copy
570 * Make a copy of a cursor or icon.
572 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
574 char *ptrOld, *ptrNew;
575 int size;
576 HGLOBAL16 hNew;
578 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
579 if (!(hInstance = GetExePtr( hInstance ))) return 0;
580 size = GlobalSize16( handle );
581 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
582 FarSetOwner( hNew, hInstance );
583 ptrNew = (char *)GlobalLock16( hNew );
584 memcpy( ptrNew, ptrOld, size );
585 GlobalUnlock16( handle );
586 GlobalUnlock16( hNew );
587 return hNew;
590 /***********************************************************************
591 * CURSORICON_IconToCursor
593 * Converts bitmap to mono and truncates if icon is too large (should
594 * probably do StretchBlt() instead).
596 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
598 HCURSOR16 hRet = 0;
599 CURSORICONINFO *pIcon = NULL;
600 HTASK16 hTask = GetCurrentTask();
601 TDB* pTask = (TDB *)GlobalLock16(hTask);
603 if(hIcon && pTask)
604 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
605 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
606 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
607 else
609 BYTE pAndBits[128];
610 BYTE pXorBits[128];
611 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
612 BYTE* psPtr, *pxbPtr = pXorBits;
613 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
614 BYTE* pbc = NULL;
616 COLORREF col;
617 CURSORICONINFO cI;
619 dprintf_icon(stddeb, "IconToCursor:[%04x] %ix%i %ibpp (bogus %ibps)\n",
620 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
622 xor_width = BITMAP_GetBitsWidth( pIcon->nWidth, bpp );
623 and_width = BITMAP_GetBitsWidth( pIcon->nWidth, 1 );
624 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
626 memset(pXorBits, 0, 128);
627 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
628 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
629 cI.nWidth = 32; cI.nHeight = 32;
630 cI.nWidthBytes = 4; /* 32x1bpp */
632 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
633 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
635 for( iy = 0; iy < maxy; iy++ )
637 unsigned shift = iy % 2;
639 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
640 (and_width > 4) ? 4 : and_width );
641 for( ix = 0; ix < maxx; ix++ )
643 if( bSemiTransparent && ((ix+shift)%2) )
645 /* set AND bit, XOR bit stays 0 */
647 pbc = pAndBits + iy * 4 + ix/8;
648 *pbc |= 0x80 >> (ix%8);
650 else
652 /* keep AND bit, set XOR bit */
654 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
655 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
656 col = COLOR_ToLogical(val);
657 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
659 pbc = pxbPtr + ix/8;
660 *pbc |= 0x80 >> (ix%8);
664 psPtr += xor_width;
665 pxbPtr += 4;
668 hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
670 if( !hRet ) /* fall back on default drag cursor */
671 hRet = CURSORICON_Copy( pTask->hInstance ,
672 CURSORICON_Load16(0,MAKEINTRESOURCE(OCR_DRAGOBJECT),
673 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE) );
676 return hRet;
680 /***********************************************************************
681 * LoadCursor16 (USER.173)
683 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
685 if (HIWORD(name))
686 dprintf_cursor( stddeb, "LoadCursor16: %04x '%s'\n",
687 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
688 else
689 dprintf_cursor( stddeb, "LoadCursor16: %04x %04x\n",
690 hInstance, LOWORD(name) );
692 return CURSORICON_Load16( hInstance, name,
693 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
697 /***********************************************************************
698 * LoadIcon16 (USER.174)
700 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
702 if (HIWORD(name))
703 dprintf_icon( stddeb, "LoadIcon: %04x '%s'\n",
704 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
705 else
706 dprintf_icon( stddeb, "LoadIcon: %04x %04x\n",
707 hInstance, LOWORD(name) );
709 return CURSORICON_Load16( hInstance, name,
710 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
711 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
715 /***********************************************************************
716 * CreateCursor16 (USER.406)
718 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
719 INT16 xHotSpot, INT16 yHotSpot,
720 INT16 nWidth, INT16 nHeight,
721 LPCVOID lpANDbits, LPCVOID lpXORbits )
723 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
725 dprintf_cursor( stddeb, "CreateCursor: %dx%d spot=%d,%d xor=%p and=%p\n",
726 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
727 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
731 /***********************************************************************
732 * CreateCursor32 (USER32.66)
734 HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
735 INT32 xHotSpot, INT32 yHotSpot,
736 INT32 nWidth, INT32 nHeight,
737 LPCVOID lpANDbits, LPCVOID lpXORbits )
739 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
741 dprintf_cursor( stddeb, "CreateCursor: %dx%d spot=%d,%d xor=%p and=%p\n",
742 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
743 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
747 /***********************************************************************
748 * CreateIcon16 (USER.407)
750 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
751 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
752 LPCVOID lpANDbits, LPCVOID lpXORbits )
754 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
756 dprintf_icon( stddeb, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
757 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
758 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
762 /***********************************************************************
763 * CreateIcon32 (USER32.74)
765 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
766 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
767 LPCVOID lpANDbits, LPCVOID lpXORbits )
769 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
771 dprintf_icon( stddeb, "CreateIcon: %dx%dx%d, xor=%p, and=%p\n",
772 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
773 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
777 /***********************************************************************
778 * CreateCursorIconIndirect (USER.408)
780 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
781 CURSORICONINFO *info,
782 LPCVOID lpANDbits,
783 LPCVOID lpXORbits )
785 HGLOBAL16 handle;
786 char *ptr;
787 int sizeAnd, sizeXor;
789 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
790 if (!hInstance || !lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
791 info->nWidthBytes = BITMAP_WIDTH_BYTES(info->nWidth,info->bBitsPerPixel);
792 sizeXor = info->nHeight * info->nWidthBytes;
793 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
794 if (!(handle = DirectResAlloc(hInstance, 0x10,
795 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
796 return 0;
797 ptr = (char *)GlobalLock16( handle );
798 memcpy( ptr, info, sizeof(*info) );
799 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
800 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
801 GlobalUnlock16( handle );
802 return handle;
806 /***********************************************************************
807 * CopyIcon16 (USER.368)
809 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
811 dprintf_icon( stddeb, "CopyIcon16: %04x %04x\n", hInstance, hIcon );
812 return CURSORICON_Copy( hInstance, hIcon );
816 /***********************************************************************
817 * CopyIcon32 (USER32.59)
819 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
821 dprintf_icon( stddeb, "CopyIcon32: %04x\n", hIcon );
822 return CURSORICON_Copy( 0, hIcon );
826 /***********************************************************************
827 * CopyCursor16 (USER.369)
829 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
831 dprintf_cursor( stddeb, "CopyCursor16: %04x %04x\n", hInstance, hCursor );
832 return CURSORICON_Copy( hInstance, hCursor );
836 /***********************************************************************
837 * DestroyIcon16 (USER.457)
839 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
841 return DestroyIcon32( hIcon );
845 /***********************************************************************
846 * DestroyIcon32 (USER32.132)
848 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
850 dprintf_icon( stddeb, "DestroyIcon: %04x\n", hIcon );
851 /* FIXME: should check for OEM icon here */
852 return (FreeResource16( hIcon ) == 0);
856 /***********************************************************************
857 * DestroyCursor16 (USER.458)
859 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
861 return DestroyCursor32( hCursor );
865 /***********************************************************************
866 * DestroyCursor32 (USER32.131)
868 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
870 dprintf_cursor( stddeb, "DestroyCursor: %04x\n", hCursor );
871 /* FIXME: should check for OEM cursor here */
872 return (FreeResource16( hCursor ) != 0);
876 /***********************************************************************
877 * DrawIcon16 (USER.84)
879 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
881 return DrawIcon32( hdc, x, y, hIcon );
885 /***********************************************************************
886 * DrawIcon32 (USER32.158)
888 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
890 CURSORICONINFO *ptr;
891 HDC32 hMemDC;
892 HBITMAP32 hXorBits, hAndBits;
893 COLORREF oldFg, oldBg;
895 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
896 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
897 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
898 (char *)(ptr+1) );
899 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
900 ptr->bBitsPerPixel, (char *)(ptr + 1)
901 + ptr->nHeight * BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
902 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
903 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
905 if (hXorBits && hAndBits)
907 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
908 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
909 SelectObject32( hMemDC, hXorBits );
910 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
911 SelectObject32( hMemDC, hBitTemp );
913 DeleteDC32( hMemDC );
914 if (hXorBits) DeleteObject32( hXorBits );
915 if (hAndBits) DeleteObject32( hAndBits );
916 GlobalUnlock16( hIcon );
917 SetTextColor32( hdc, oldFg );
918 SetBkColor32( hdc, oldBg );
919 return TRUE;
923 /***********************************************************************
924 * DumpIcon (USER.459)
926 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
927 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
929 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
930 int sizeAnd, sizeXor;
932 if (!info) return 0;
933 sizeXor = info->nHeight * info->nWidthBytes;
934 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
935 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
936 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
937 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
938 return MAKELONG( sizeXor, sizeXor );
942 /***********************************************************************
943 * CURSORICON_SetCursor
945 * Change the X cursor. Helper function for SetCursor() and ShowCursor().
947 static BOOL32 CURSORICON_SetCursor( HCURSOR16 hCursor )
949 Pixmap pixmapBits, pixmapMask, pixmapAll;
950 XColor fg, bg;
951 Cursor cursor = None;
953 if (!hCursor) /* Create an empty cursor */
955 static const char data[] = { 0 };
957 bg.red = bg.green = bg.blue = 0x0000;
958 pixmapBits = XCreateBitmapFromData( display, rootWindow, data, 1, 1 );
959 if (pixmapBits)
961 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
962 &bg, &bg, 0, 0 );
963 XFreePixmap( display, pixmapBits );
966 else /* Create the X cursor from the bits */
968 CURSORICONINFO *ptr;
969 XImage *image;
971 if (!(ptr = (CURSORICONINFO*)GlobalLock16( hCursor ))) return FALSE;
972 if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
974 fprintf( stderr, "Cursor %04x has more than 1 bpp!\n", hCursor );
975 return FALSE;
978 /* Create a pixmap and transfer all the bits to it */
980 /* NOTE: Following hack works, but only because XFree depth
981 * 1 images really use 1 bit/pixel (and so the same layout
982 * as the Windows cursor data). Perhaps use a more generic
983 * algorithm here.
985 pixmapAll = XCreatePixmap( display, rootWindow,
986 ptr->nWidth, ptr->nHeight * 2, 1 );
987 image = XCreateImage( display, DefaultVisualOfScreen(screen),
988 1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
989 ptr->nHeight * 2, 16, ptr->nWidthBytes);
990 if (image)
992 extern void _XInitImageFuncPtrs( XImage* );
993 image->byte_order = MSBFirst;
994 image->bitmap_bit_order = MSBFirst;
995 image->bitmap_unit = 16;
996 _XInitImageFuncPtrs(image);
997 if (pixmapAll)
998 XPutImage( display, pixmapAll, BITMAP_monoGC, image,
999 0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
1000 image->data = NULL;
1001 XDestroyImage( image );
1004 /* Now create the 2 pixmaps for bits and mask */
1006 pixmapBits = XCreatePixmap( display, rootWindow,
1007 ptr->nWidth, ptr->nHeight, 1 );
1008 pixmapMask = XCreatePixmap( display, rootWindow,
1009 ptr->nWidth, ptr->nHeight, 1 );
1011 /* Make sure everything went OK so far */
1013 if (pixmapBits && pixmapMask && pixmapAll)
1015 /* We have to do some magic here, as cursors are not fully
1016 * compatible between Windows and X11. Under X11, there
1017 * are only 3 possible color cursor: black, white and
1018 * masked. So we map the 4th Windows color (invert the
1019 * bits on the screen) to black. This require some boolean
1020 * arithmetic:
1022 * Windows | X11
1023 * Xor And Result | Bits Mask Result
1024 * 0 0 black | 0 1 background
1025 * 0 1 no change | X 0 no change
1026 * 1 0 white | 1 1 foreground
1027 * 1 1 inverted | 0 1 background
1029 * which gives:
1030 * Bits = 'Xor' and not 'And'
1031 * Mask = 'Xor' or not 'And'
1033 * FIXME: apparently some servers do support 'inverted' color.
1034 * I don't know if it's correct per the X spec, but maybe
1035 * we ought to take advantage of it. -- AJ
1037 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1038 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1039 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1040 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1041 XSetFunction( display, BITMAP_monoGC, GXandReverse );
1042 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1043 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1044 XSetFunction( display, BITMAP_monoGC, GXorReverse );
1045 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1046 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1047 XSetFunction( display, BITMAP_monoGC, GXcopy );
1048 fg.red = fg.green = fg.blue = 0xffff;
1049 bg.red = bg.green = bg.blue = 0x0000;
1050 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
1051 &fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
1054 /* Now free everything */
1056 if (pixmapAll) XFreePixmap( display, pixmapAll );
1057 if (pixmapBits) XFreePixmap( display, pixmapBits );
1058 if (pixmapMask) XFreePixmap( display, pixmapMask );
1059 GlobalUnlock16( hCursor );
1062 if (cursor == None) return FALSE;
1063 if (CURSORICON_XCursor != None) XFreeCursor( display, CURSORICON_XCursor );
1064 CURSORICON_XCursor = cursor;
1066 if (rootWindow != DefaultRootWindow(display))
1068 /* Set the cursor on the desktop window */
1069 XDefineCursor( display, rootWindow, cursor );
1071 else
1073 /* Set the same cursor for all top-level windows */
1074 HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD );
1075 while(hwnd)
1077 Window win = WIN_GetXWindow( hwnd );
1078 if (win) XDefineCursor( display, win, cursor );
1079 hwnd = GetWindow32( hwnd, GW_HWNDNEXT );
1082 return TRUE;
1086 /***********************************************************************
1087 * SetCursor16 (USER.69)
1089 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1091 return (HCURSOR16)SetCursor32( hCursor );
1095 /***********************************************************************
1096 * SetCursor32 (USER32.471)
1098 HCURSOR32 WINAPI SetCursor32( HCURSOR32 hCursor )
1100 HCURSOR32 hOldCursor;
1102 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1103 dprintf_cursor( stddeb, "SetCursor: %04x\n", hCursor );
1104 hOldCursor = hActiveCursor;
1105 hActiveCursor = hCursor;
1106 /* Change the cursor shape only if it is visible */
1107 if (CURSOR_ShowCount >= 0)
1108 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1109 return hOldCursor;
1113 /***********************************************************************
1114 * SetCursorPos16 (USER.70)
1116 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1118 SetCursorPos32( x, y );
1122 /***********************************************************************
1123 * SetCursorPos32 (USER32.473)
1125 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1127 dprintf_cursor( stddeb, "SetCursorPos: x=%d y=%d\n", x, y );
1128 XWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, x, y );
1129 return TRUE;
1133 /***********************************************************************
1134 * ShowCursor16 (USER.71)
1136 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1138 return ShowCursor32( bShow );
1142 /***********************************************************************
1143 * ShowCursor32 (USER32.529)
1145 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1147 dprintf_cursor( stddeb, "ShowCursor: %d, count=%d\n",
1148 bShow, CURSOR_ShowCount );
1150 if (bShow)
1152 if (++CURSOR_ShowCount == 0) /* Show it */
1153 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1155 else
1157 if (--CURSOR_ShowCount == -1) /* Hide it */
1158 CALL_LARGE_STACK( CURSORICON_SetCursor, 0 );
1160 return CURSOR_ShowCount;
1164 /***********************************************************************
1165 * GetCursor16 (USER.247)
1167 HCURSOR16 WINAPI GetCursor16(void)
1169 return hActiveCursor;
1173 /***********************************************************************
1174 * GetCursor32 (USER32.226)
1176 HCURSOR32 WINAPI GetCursor32(void)
1178 return hActiveCursor;
1182 /***********************************************************************
1183 * ClipCursor16 (USER.16)
1185 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1187 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1188 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1189 return TRUE;
1193 /***********************************************************************
1194 * ClipCursor32 (USER32.52)
1196 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1198 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1199 else CopyRect32( &CURSOR_ClipRect, rect );
1200 return TRUE;
1204 /***********************************************************************
1205 * GetCursorPos16 (USER.17)
1207 void WINAPI GetCursorPos16( POINT16 *pt )
1209 Window root, child;
1210 int rootX, rootY, childX, childY;
1211 unsigned int mousebut;
1213 if (!pt) return;
1214 if (!XQueryPointer( display, rootWindow, &root, &child,
1215 &rootX, &rootY, &childX, &childY, &mousebut ))
1216 pt->x = pt->y = 0;
1217 else
1219 pt->x = childX;
1220 pt->y = childY;
1222 dprintf_cursor(stddeb, "GetCursorPos: ret=%d,%d\n", pt->x, pt->y );
1226 /***********************************************************************
1227 * GetCursorPos32 (USER32.228)
1229 void WINAPI GetCursorPos32( POINT32 *pt )
1231 POINT16 pt16;
1232 GetCursorPos16( &pt16 );
1233 if (pt) CONV_POINT16TO32( &pt16, pt );
1237 /***********************************************************************
1238 * GetClipCursor16 (USER.309)
1240 void WINAPI GetClipCursor16( RECT16 *rect )
1242 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1246 /***********************************************************************
1247 * GetClipCursor32 (USER32.220)
1249 void WINAPI GetClipCursor32( RECT32 *rect )
1251 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1254 /**********************************************************************
1255 * LookupIconIdFromDirectoryEx16 (USER.364)
1257 * FIXME: exact parameter sizes
1259 UINT16 WINAPI LookupIconIdFromDirectoryEx16( CURSORICONDIR *dir, BOOL16 bIcon,
1260 INT16 width, INT16 height, UINT16 cFlag )
1262 UINT16 retVal = 0;
1263 if( dir && !dir->idReserved && (dir->idType & 3) )
1265 int colors = (cFlag == LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
1266 if( bIcon )
1268 ICONDIRENTRY* entry;
1269 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1270 if( entry ) retVal = entry->wResId;
1272 else
1274 CURSORDIRENTRY* entry;
1275 entry = CURSORICON_FindBestCursor( dir, width, height );
1276 if( entry ) retVal = entry->wResId;
1279 else dprintf_cursor(stddeb,"IconId: invalid resource directory\n");
1280 return retVal;
1283 /**********************************************************************
1284 * LookupIconIdFromDirectoryEx32 (USER32.379)
1286 INT32 WINAPI LookupIconIdFromDirectoryEx32( CURSORICONDIR *dir, BOOL32 bIcon,
1287 INT32 width, INT32 height, UINT32 cFlag )
1289 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1292 /**********************************************************************
1293 * LookupIconIdFromDirectory (USER32.378)
1295 INT32 WINAPI LookupIconIdFromDirectory( CURSORICONDIR *dir, BOOL32 bIcon )
1297 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1298 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1299 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1302 /**********************************************************************
1303 * GetIconID (USER.455)
1305 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1307 CURSORICONDIR *lpDir = (CURSORICONDIR *)GlobalLock16(hResource);
1309 dprintf_cursor( stddeb, "GetIconID: hRes=%04x, entries=%i\n",
1310 hResource, lpDir ? lpDir->idCount : 0);
1312 switch(resType)
1314 case RT_CURSOR:
1315 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1316 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1317 case RT_ICON:
1318 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1319 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1320 default:
1321 fprintf( stderr, "GetIconID: invalid res type %ld\n", resType );
1323 return 0;
1326 /**********************************************************************
1327 * LoadCursorIconHandler (USER.336)
1329 * Supposed to load resources of Windows 2.x applications.
1331 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1333 fprintf(stderr,"hModule[%04x]: old 2.x resources are not supported!\n", hModule);
1334 return (HGLOBAL16)0;
1337 /**********************************************************************
1338 * LoadDIBIconHandler (USER.357)
1340 * RT_ICON resource loader, installed by USER_SignalProc when module
1341 * is initialized.
1343 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1345 /* If hResource is zero we must allocate a new memory block, if it's
1346 * non-zero but GlobalLock() returns NULL then it was discarded and
1347 * we have to recommit some memory, otherwise we just need to check
1348 * the block size. See LoadProc() in 16-bit SDK for more.
1351 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1352 if( hMemObj )
1354 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1355 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1356 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1357 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1359 return hMemObj;
1362 /**********************************************************************
1363 * LoadDIBCursorHandler (USER.356)
1365 * RT_CURSOR resource loader. Same as above.
1367 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1369 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1370 if( hMemObj )
1372 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1373 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1374 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1375 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1377 return hMemObj;
1380 /**********************************************************************
1381 * LoadIconHandler (USER.456)
1383 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1385 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1387 dprintf_cursor(stddeb,"LoadIconHandler: hRes=%04x\n",hResource);
1389 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1390 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1393 /***********************************************************************
1394 * LoadCursorW (USER32.361)
1396 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1398 return CURSORICON_Load32( hInstance, name,
1399 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
1402 /***********************************************************************
1403 * LoadCursorA (USER32.358)
1405 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1407 HCURSOR32 res=0;
1408 if(!HIWORD(name))
1409 return LoadCursor32W(hInstance,(LPCWSTR)name);
1410 else
1412 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1413 res = LoadCursor32W(hInstance, uni);
1414 HeapFree( GetProcessHeap(), 0, uni);
1416 return res;
1419 /***********************************************************************
1420 * LoadIconW (USER32.363)
1422 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1424 return CURSORICON_Load32( hInstance, name,
1425 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1426 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
1429 /***********************************************************************
1430 * LoadIconA (USER32.362)
1432 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1434 HICON32 res=0;
1436 if( !HIWORD(name) )
1437 return LoadIcon32W(hInstance, (LPCWSTR)name);
1438 else
1440 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1441 res = LoadIcon32W( hInstance, uni );
1442 HeapFree( GetProcessHeap(), 0, uni );
1444 return res;
1447 /**********************************************************************
1448 * GetIconInfo (USER32.241)