Release 980517
[wine/testsucceed.git] / objects / cursoricon.c
blob74da477486e496320f8155ebb247be1ba583fe4a
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 "debug.h"
42 #include "task.h"
43 #include "user.h"
44 #include "keyboard.h"
46 extern UINT16 COLOR_GetSystemPaletteSize();
47 extern void _XInitImageFuncPtrs(XImage *);
49 Cursor CURSORICON_XCursor = None; /* Current X cursor */
50 static HCURSOR32 hActiveCursor = 0; /* Active cursor */
51 static INT32 CURSOR_ShowCount = 0; /* Cursor display count */
52 static RECT32 CURSOR_ClipRect; /* Cursor clipping rect */
54 /**********************************************************************
55 * CURSORICON_FindBestIcon
57 * Find the icon closest to the requested size and number of colors.
59 static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
60 int height, int colors )
62 int i, maxcolors, maxwidth, maxheight;
63 ICONDIRENTRY *entry, *bestEntry = NULL;
65 if (dir->idCount < 1)
67 WARN(icon, "Empty directory!\n" );
68 return NULL;
70 if (dir->idCount == 1) return &dir->idEntries[0].icon; /* No choice... */
72 /* First find the exact size with less colors */
74 maxcolors = 0;
75 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
76 if ((entry->bWidth == width) && (entry->bHeight == height) &&
77 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
79 bestEntry = entry;
80 maxcolors = entry->bColorCount;
82 if (bestEntry) return bestEntry;
84 /* First find the exact size with more colors */
86 maxcolors = 255;
87 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
88 if ((entry->bWidth == width) && (entry->bHeight == height) &&
89 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
91 bestEntry = entry;
92 maxcolors = entry->bColorCount;
94 if (bestEntry) return bestEntry;
96 /* Now find a smaller one with less colors */
98 maxcolors = maxwidth = maxheight = 0;
99 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
100 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
101 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
102 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
104 bestEntry = entry;
105 maxwidth = entry->bWidth;
106 maxheight = entry->bHeight;
107 maxcolors = entry->bColorCount;
109 if (bestEntry) return bestEntry;
111 /* Now find a smaller one with more colors */
113 maxcolors = 255;
114 maxwidth = maxheight = 0;
115 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
116 if ((entry->bWidth <= width) && (entry->bHeight <= height) &&
117 (entry->bWidth >= maxwidth) && (entry->bHeight >= maxheight) &&
118 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
120 bestEntry = entry;
121 maxwidth = entry->bWidth;
122 maxheight = entry->bHeight;
123 maxcolors = entry->bColorCount;
125 if (bestEntry) return bestEntry;
127 /* Now find a larger one with less colors */
129 maxcolors = 0;
130 maxwidth = maxheight = 255;
131 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
132 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
133 (entry->bColorCount <= colors) && (entry->bColorCount > maxcolors))
135 bestEntry = entry;
136 maxwidth = entry->bWidth;
137 maxheight = entry->bHeight;
138 maxcolors = entry->bColorCount;
140 if (bestEntry) return bestEntry;
142 /* Now find a larger one with more colors */
144 maxcolors = maxwidth = maxheight = 255;
145 for (i = 0, entry = &dir->idEntries[0].icon; i < dir->idCount; i++,entry++)
146 if ((entry->bWidth <= maxwidth) && (entry->bHeight <= maxheight) &&
147 (entry->bColorCount > colors) && (entry->bColorCount <= maxcolors))
149 bestEntry = entry;
150 maxwidth = entry->bWidth;
151 maxheight = entry->bHeight;
152 maxcolors = entry->bColorCount;
155 return bestEntry;
159 /**********************************************************************
160 * CURSORICON_FindBestCursor
162 * Find the cursor closest to the requested size.
164 static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
165 int width, int height )
167 int i, maxwidth, maxheight;
168 CURSORDIRENTRY *entry, *bestEntry = NULL;
170 if (dir->idCount < 1)
172 WARN(cursor, "Empty directory!\n" );
173 return NULL;
175 if (dir->idCount == 1) return &dir->idEntries[0].cursor; /* No choice... */
177 /* First find the largest one smaller than or equal to the requested size*/
179 maxwidth = maxheight = 0;
180 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
181 if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
182 (entry->wWidth > maxwidth) && (entry->wHeight > maxheight))
184 bestEntry = entry;
185 maxwidth = entry->wWidth;
186 maxheight = entry->wHeight;
188 if (bestEntry) return bestEntry;
190 /* Now find the smallest one larger than the requested size */
192 maxwidth = maxheight = 255;
193 for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
194 if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight))
196 bestEntry = entry;
197 maxwidth = entry->wWidth;
198 maxheight = entry->wHeight;
201 return bestEntry;
205 /**********************************************************************
206 * CURSORICON_LoadDirEntry16
208 * Load the icon/cursor directory for a given resource name and find the
209 * best matching entry.
211 static BOOL32 CURSORICON_LoadDirEntry16( HINSTANCE32 hInstance, SEGPTR name,
212 INT32 width, INT32 height, INT32 colors,
213 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
215 HRSRC16 hRsrc;
216 HGLOBAL16 hMem;
217 CURSORICONDIR *dir;
218 CURSORICONDIRENTRY *entry = NULL;
220 if (!(hRsrc = FindResource16( hInstance, name,
221 fCursor ? RT_GROUP_CURSOR16 : RT_GROUP_ICON16 )))
222 return FALSE;
223 if (!(hMem = LoadResource16( hInstance, hRsrc ))) return FALSE;
224 if ((dir = (CURSORICONDIR *)LockResource16( hMem )))
226 if (fCursor)
227 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
228 width, height );
229 else
230 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
231 width, height, colors );
232 if (entry) *dirEntry = *entry;
234 FreeResource16( hMem );
235 return (entry != NULL);
239 /**********************************************************************
240 * CURSORICON_LoadDirEntry32
242 * Load the icon/cursor directory for a given resource name and find the
243 * best matching entry.
245 static BOOL32 CURSORICON_LoadDirEntry32( HINSTANCE32 hInstance, LPCWSTR name,
246 INT32 width, INT32 height, INT32 colors,
247 BOOL32 fCursor, CURSORICONDIRENTRY *dirEntry )
249 HANDLE32 hRsrc;
250 HANDLE32 hMem;
251 CURSORICONDIR *dir;
252 CURSORICONDIRENTRY *entry = NULL;
254 if (!(hRsrc = FindResource32W( hInstance, name,
255 fCursor ? RT_GROUP_CURSOR32W : RT_GROUP_ICON32W )))
256 return FALSE;
257 if (!(hMem = LoadResource32( hInstance, hRsrc ))) return FALSE;
258 if ((dir = (CURSORICONDIR*)LockResource32( hMem )))
260 if (fCursor)
261 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
262 width, height );
263 else
264 entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
265 width, height, colors );
266 if (entry) *dirEntry = *entry;
268 FreeResource32( hMem );
269 return (entry != NULL);
273 /**********************************************************************
274 * CURSORICON_CreateFromResource
276 * Create a cursor or icon from in-memory resource template.
278 * FIXME: Adjust icon size when width and height are nonzero (stretchblt).
279 * Convert to mono when cFlag is LR_MONOCHROME. Do something
280 * with cbSize parameter as well.
282 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
283 UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion,
284 INT32 width, INT32 height, UINT32 cFlag )
286 int sizeAnd, sizeXor;
287 HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */
288 BITMAPOBJ *bmpXor, *bmpAnd;
289 POINT16 hotspot = { 0 ,0 };
290 BITMAPINFO *bmi;
291 HDC32 hdc;
293 TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
294 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
295 bIcon ? "icon" : "cursor", cFlag ? "mono" : "" );
296 if (dwVersion == 0x00020000)
298 FIXME(cursor,"\t2.xx resources are not supported\n");
299 return 0;
302 if (bIcon)
303 bmi = (BITMAPINFO *)bits;
304 else /* get the hotspot */
306 POINT16 *pt = (POINT16 *)bits;
307 hotspot = *pt;
308 bmi = (BITMAPINFO *)(pt + 1);
311 /* Check bitmap header */
313 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
314 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
315 bmi->bmiHeader.biCompression != BI_RGB) )
317 WARN(cursor,"\tinvalid resource bitmap header.\n");
318 return 0;
321 if( (hdc = GetDC32( 0 )) )
323 BITMAPINFO* pInfo;
324 INT32 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
326 /* Make sure we have room for the monochrome bitmap later on.
327 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
328 * up to and including the biBitCount. In-memory icon resource
329 * format is as follows:
331 * BITMAPINFOHEADER icHeader // DIB header
332 * RGBQUAD icColors[] // Color table
333 * BYTE icXOR[] // DIB bits for XOR mask
334 * BYTE icAND[] // DIB bits for AND mask
337 if( (pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
338 MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))) )
340 memcpy( pInfo, bmi, size );
341 pInfo->bmiHeader.biHeight /= 2;
343 /* Create the XOR bitmap */
345 hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
346 (char*)bmi + size, pInfo, DIB_RGB_COLORS );
347 if( hXorBits )
349 char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
350 DIB_GetDIBWidthBytes(bmi->bmiHeader.biWidth,
351 bmi->bmiHeader.biBitCount) / 2;
353 pInfo->bmiHeader.biBitCount = 1;
354 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
356 RGBQUAD *rgb = pInfo->bmiColors;
358 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
359 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
360 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
361 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
363 else
365 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
367 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
368 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
371 /* Create the AND bitmap */
373 hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT,
374 bits, pInfo, DIB_RGB_COLORS );
375 if( !hAndBits ) DeleteObject32( hXorBits );
377 HeapFree( GetProcessHeap(), 0, pInfo );
379 ReleaseDC32( 0, hdc );
382 if( !hXorBits || !hAndBits )
384 WARN(cursor,"\tunable to create an icon bitmap.\n");
385 return 0;
388 /* Now create the CURSORICONINFO structure */
390 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
391 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
392 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
393 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
395 if (hObj) hObj = GlobalReAlloc16( hObj,
396 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
397 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
398 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
399 if (hObj)
401 CURSORICONINFO *info;
403 /* Make it owned by the module */
404 if (hInstance) FarSetOwner( hObj, GetExePtr(hInstance) );
406 info = (CURSORICONINFO *)GlobalLock16( hObj );
407 info->ptHotSpot.x = hotspot.x;
408 info->ptHotSpot.y = hotspot.y;
409 info->nWidth = bmpXor->bitmap.bmWidth;
410 info->nHeight = bmpXor->bitmap.bmHeight;
411 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
412 info->bPlanes = bmpXor->bitmap.bmPlanes;
413 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
415 /* Transfer the bitmap bits to the CURSORICONINFO structure */
417 GetBitmapBits32( hAndBits, sizeAnd, (char *)(info + 1) );
418 GetBitmapBits32( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
419 GlobalUnlock16( hObj );
422 DeleteObject32( hXorBits );
423 DeleteObject32( hAndBits );
424 return hObj;
428 /**********************************************************************
429 * CreateIconFromResourceEx16 (USER.450)
431 * FIXME: not sure about exact parameter types
433 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
434 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
436 TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
437 if( pTask )
438 return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
439 width, height, cFlag );
440 return 0;
444 /**********************************************************************
445 * CreateIconFromResource (USER32.76)
446 * FIXME:
447 * bon@elektron.ikp.physik.tu-darmstadt.de 971130: Test with weditres
448 * showed only blank layout. Couldn't determine if this is a problem
449 * with CreateIconFromResource32 or the application. The application
450 * windows behaves strange (no redraw) before CreateIconFromResource32
452 HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
453 BOOL32 bIcon, DWORD dwVersion)
455 HICON32 ret;
456 ret = CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, 0,0,0);
457 FIXME(icon,"probably only a stub\n");
458 TRACE(icon, "%s at %p size %d winver %d return 0x%04x\n",
459 (bIcon)?"Icon":"Cursor",bits,cbSize,bIcon,ret);
460 return ret;
464 /**********************************************************************
465 * CreateIconFromResourceEx32 (USER32.77)
467 HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
468 BOOL32 bIcon, DWORD dwVersion,
469 INT32 width, INT32 height,
470 UINT32 cFlag )
472 return CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, width, height, cFlag );
476 /**********************************************************************
477 * CURSORICON_Load16
479 * Load a cursor or icon from a 16-bit resource.
481 static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
482 INT32 width, INT32 height, INT32 colors,
483 BOOL32 fCursor )
485 HGLOBAL16 handle;
486 HRSRC16 hRsrc;
487 CURSORICONDIRENTRY dirEntry;
489 if (!hInstance) /* OEM cursor/icon */
491 if (HIWORD(name)) /* Check for '#xxx' name */
493 char *ptr = PTR_SEG_TO_LIN( name );
494 if (ptr[0] != '#') return 0;
495 if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
497 return OBM_LoadCursorIcon( LOWORD(name), fCursor );
500 /* Find the best entry in the directory */
502 if ( !CURSORICON_LoadDirEntry16( hInstance, name, width, height,
503 colors, fCursor, &dirEntry ) ) return 0;
504 /* Load the resource */
506 if ( (hRsrc = FindResource16( hInstance,
507 MAKEINTRESOURCE16( dirEntry.icon.wResId ),
508 fCursor ? RT_CURSOR16 : RT_ICON16 )) )
510 /* 16-bit icon or cursor resources are processed
511 * transparently by the LoadResource16() via custom
512 * resource handlers set by SetResourceHandler().
515 if ( (handle = LoadResource16( hInstance, hRsrc )) )
516 return handle;
518 return 0;
521 /**********************************************************************
522 * CURSORICON_Load32
524 * Load a cursor or icon from a 32-bit resource.
526 static HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
527 int width, int height, int colors,
528 BOOL32 fCursor )
530 HANDLE32 handle;
531 HANDLE32 hRsrc;
532 CURSORICONDIRENTRY dirEntry;
534 if(!hInstance) /* OEM cursor/icon */
536 WORD resid;
537 if(HIWORD(name))
539 LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
540 if( ansi[0]=='#') /*Check for '#xxx' name */
542 resid = atoi(ansi+1);
543 HeapFree( GetProcessHeap(), 0, ansi );
545 else
547 HeapFree( GetProcessHeap(), 0, ansi );
548 return 0;
551 else resid = LOWORD(name);
552 return OBM_LoadCursorIcon(resid, fCursor);
555 /* Find the best entry in the directory */
557 if ( !CURSORICON_LoadDirEntry32( hInstance, name, width, height,
558 colors, fCursor, &dirEntry ) ) return 0;
559 /* Load the resource */
561 if ( (hRsrc = FindResource32W( hInstance,
562 MAKEINTRESOURCE32W( dirEntry.icon.wResId ),
563 fCursor ? RT_CURSOR32W : RT_ICON32W )) )
565 HANDLE32 h = 0;
566 if ( (handle = LoadResource32( hInstance, hRsrc )) )
568 /* Hack to keep LoadCursor/Icon32() from spawning multiple
569 * copies of the same object.
571 #define pRsrcEntry ((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
572 if( !pRsrcEntry->ResourceHandle )
574 LPBYTE bits = (LPBYTE)LockResource32( handle );
575 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
576 !fCursor, 0x00030000, width, height, LR_DEFAULTCOLOR );
577 pRsrcEntry->ResourceHandle = h;
579 else h = pRsrcEntry->ResourceHandle;
580 #undef pRsrcEntry
582 return h;
584 return 0;
588 /***********************************************************************
589 * CURSORICON_Copy
591 * Make a copy of a cursor or icon.
593 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
595 char *ptrOld, *ptrNew;
596 int size;
597 HGLOBAL16 hNew;
599 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
600 if (!(hInstance = GetExePtr( hInstance ))) return 0;
601 size = GlobalSize16( handle );
602 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
603 FarSetOwner( hNew, hInstance );
604 ptrNew = (char *)GlobalLock16( hNew );
605 memcpy( ptrNew, ptrOld, size );
606 GlobalUnlock16( handle );
607 GlobalUnlock16( hNew );
608 return hNew;
611 /***********************************************************************
612 * CURSORICON_IconToCursor
614 * Converts bitmap to mono and truncates if icon is too large (should
615 * probably do StretchBlt() instead).
617 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
619 HCURSOR16 hRet = 0;
620 CURSORICONINFO *pIcon = NULL;
621 HTASK16 hTask = GetCurrentTask();
622 TDB* pTask = (TDB *)GlobalLock16(hTask);
624 if(hIcon && pTask)
625 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
626 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
627 hRet = CURSORICON_Copy( pTask->hInstance, hIcon );
628 else
630 BYTE pAndBits[128];
631 BYTE pXorBits[128];
632 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
633 BYTE* psPtr, *pxbPtr = pXorBits;
634 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
635 BYTE* pbc = NULL;
637 COLORREF col;
638 CURSORICONINFO cI;
640 TRACE(icon, "[%04x] %ix%i %ibpp (bogus %ibps)\n",
641 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
643 xor_width = BITMAP_GetBitsWidth( pIcon->nWidth, bpp );
644 and_width = BITMAP_GetBitsWidth( pIcon->nWidth, 1 );
645 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
647 memset(pXorBits, 0, 128);
648 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
649 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
650 cI.nWidth = 32; cI.nHeight = 32;
651 cI.nWidthBytes = 4; /* 32x1bpp */
653 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
654 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
656 for( iy = 0; iy < maxy; iy++ )
658 unsigned shift = iy % 2;
660 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
661 (and_width > 4) ? 4 : and_width );
662 for( ix = 0; ix < maxx; ix++ )
664 if( bSemiTransparent && ((ix+shift)%2) )
666 /* set AND bit, XOR bit stays 0 */
668 pbc = pAndBits + iy * 4 + ix/8;
669 *pbc |= 0x80 >> (ix%8);
671 else
673 /* keep AND bit, set XOR bit */
675 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
676 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
677 col = COLOR_ToLogical(val);
678 if( (GetRValue(col) + GetGValue(col) + GetBValue(col)) > 0x180 )
680 pbc = pxbPtr + ix/8;
681 *pbc |= 0x80 >> (ix%8);
685 psPtr += xor_width;
686 pxbPtr += 4;
689 hRet = CreateCursorIconIndirect( pTask->hInstance , &cI, pAndBits, pXorBits);
691 if( !hRet ) /* fall back on default drag cursor */
692 hRet = CURSORICON_Copy( pTask->hInstance ,
693 CURSORICON_Load16(0,MAKEINTRESOURCE16(OCR_DRAGOBJECT),
694 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE) );
697 return hRet;
701 /***********************************************************************
702 * LoadCursor16 (USER.173)
704 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
706 if (HIWORD(name))
707 TRACE(cursor, "%04x '%s'\n",
708 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
709 else
710 TRACE(cursor, "%04x %04x\n",
711 hInstance, LOWORD(name) );
713 return CURSORICON_Load16( hInstance, name,
714 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
718 /***********************************************************************
719 * LoadIcon16 (USER.174)
721 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
723 if (HIWORD(name))
724 TRACE(icon, "%04x '%s'\n",
725 hInstance, (char *)PTR_SEG_TO_LIN( name ) );
726 else
727 TRACE(icon, "%04x %04x\n",
728 hInstance, LOWORD(name) );
730 return CURSORICON_Load16( hInstance, name,
731 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
732 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
736 /***********************************************************************
737 * CreateCursor16 (USER.406)
739 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
740 INT16 xHotSpot, INT16 yHotSpot,
741 INT16 nWidth, INT16 nHeight,
742 LPCVOID lpANDbits, LPCVOID lpXORbits )
744 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
746 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
747 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
748 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
752 /***********************************************************************
753 * CreateCursor32 (USER32.67)
755 HCURSOR32 WINAPI CreateCursor32( HINSTANCE32 hInstance,
756 INT32 xHotSpot, INT32 yHotSpot,
757 INT32 nWidth, INT32 nHeight,
758 LPCVOID lpANDbits, LPCVOID lpXORbits )
760 CURSORICONINFO info = { { xHotSpot, yHotSpot }, nWidth, nHeight, 0, 1, 1 };
762 TRACE(cursor, "%dx%d spot=%d,%d xor=%p and=%p\n",
763 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
764 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
768 /***********************************************************************
769 * CreateIcon16 (USER.407)
771 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
772 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
773 LPCVOID lpANDbits, LPCVOID lpXORbits )
775 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
777 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
778 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
779 return CreateCursorIconIndirect( hInstance, &info, lpANDbits, lpXORbits );
783 /***********************************************************************
784 * CreateIcon32 (USER32.75)
786 HICON32 WINAPI CreateIcon32( HINSTANCE32 hInstance, INT32 nWidth,
787 INT32 nHeight, BYTE bPlanes, BYTE bBitsPixel,
788 LPCVOID lpANDbits, LPCVOID lpXORbits )
790 CURSORICONINFO info = { { 0, 0 }, nWidth, nHeight, 0, bPlanes, bBitsPixel};
792 TRACE(icon, "%dx%dx%d, xor=%p, and=%p\n",
793 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
794 return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
798 /***********************************************************************
799 * CreateCursorIconIndirect (USER.408)
801 HGLOBAL16 WINAPI CreateCursorIconIndirect( HINSTANCE16 hInstance,
802 CURSORICONINFO *info,
803 LPCVOID lpANDbits,
804 LPCVOID lpXORbits )
806 HGLOBAL16 handle;
807 char *ptr;
808 int sizeAnd, sizeXor;
810 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
811 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
812 info->nWidthBytes = BITMAP_WIDTH_BYTES(info->nWidth,info->bBitsPerPixel);
813 sizeXor = info->nHeight * info->nWidthBytes;
814 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
815 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
816 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
817 return 0;
818 if (hInstance) FarSetOwner( handle, hInstance );
819 ptr = (char *)GlobalLock16( handle );
820 memcpy( ptr, info, sizeof(*info) );
821 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
822 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
823 GlobalUnlock16( handle );
824 return handle;
828 /***********************************************************************
829 * CopyIcon16 (USER.368)
831 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
833 TRACE(icon, "%04x %04x\n", hInstance, hIcon );
834 return CURSORICON_Copy( hInstance, hIcon );
838 /***********************************************************************
839 * CopyIcon32 (USER32.60)
841 HICON32 WINAPI CopyIcon32( HICON32 hIcon )
843 HTASK16 hTask = GetCurrentTask ();
844 TDB* pTask = (TDB *) GlobalLock16 (hTask);
845 TRACE(icon, "%04x\n", hIcon );
846 return CURSORICON_Copy( pTask->hInstance, hIcon );
850 /***********************************************************************
851 * CopyCursor16 (USER.369)
853 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
855 TRACE(cursor, "%04x %04x\n", hInstance, hCursor );
856 return CURSORICON_Copy( hInstance, hCursor );
860 /***********************************************************************
861 * DestroyIcon16 (USER.457)
863 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
865 return DestroyIcon32( hIcon );
869 /***********************************************************************
870 * DestroyIcon32 (USER32.133)
872 BOOL32 WINAPI DestroyIcon32( HICON32 hIcon )
874 TRACE(icon, "%04x\n", hIcon );
875 /* FIXME: should check for OEM icon here */
876 return (FreeResource16( hIcon ) == 0);
880 /***********************************************************************
881 * DestroyCursor16 (USER.458)
883 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
885 return DestroyCursor32( hCursor );
889 /***********************************************************************
890 * DestroyCursor32 (USER32.132)
892 BOOL32 WINAPI DestroyCursor32( HCURSOR32 hCursor )
894 TRACE(cursor, "%04x\n", hCursor );
895 /* FIXME: should check for OEM cursor here */
896 return (FreeResource16( hCursor ) == 0);
900 /***********************************************************************
901 * DrawIcon16 (USER.84)
903 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
905 return DrawIcon32( hdc, x, y, hIcon );
909 /***********************************************************************
910 * DrawIcon32 (USER32.159)
912 BOOL32 WINAPI DrawIcon32( HDC32 hdc, INT32 x, INT32 y, HICON32 hIcon )
914 CURSORICONINFO *ptr;
915 HDC32 hMemDC;
916 HBITMAP32 hXorBits, hAndBits;
917 COLORREF oldFg, oldBg;
919 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
920 if (!(hMemDC = CreateCompatibleDC32( hdc ))) return FALSE;
921 hAndBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, 1, 1,
922 (char *)(ptr+1) );
923 hXorBits = CreateBitmap32( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
924 ptr->bBitsPerPixel, (char *)(ptr + 1)
925 + ptr->nHeight * BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
926 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
927 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
929 if (hXorBits && hAndBits)
931 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
932 BitBlt32( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
933 SelectObject32( hMemDC, hXorBits );
934 BitBlt32(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
935 SelectObject32( hMemDC, hBitTemp );
937 DeleteDC32( hMemDC );
938 if (hXorBits) DeleteObject32( hXorBits );
939 if (hAndBits) DeleteObject32( hAndBits );
940 GlobalUnlock16( hIcon );
941 SetTextColor32( hdc, oldFg );
942 SetBkColor32( hdc, oldBg );
943 return TRUE;
947 /***********************************************************************
948 * DumpIcon (USER.459)
950 DWORD WINAPI DumpIcon( SEGPTR pInfo, WORD *lpLen,
951 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
953 CURSORICONINFO *info = PTR_SEG_TO_LIN( pInfo );
954 int sizeAnd, sizeXor;
956 if (!info) return 0;
957 sizeXor = info->nHeight * info->nWidthBytes;
958 sizeAnd = info->nHeight * BITMAP_WIDTH_BYTES( info->nWidth, 1 );
959 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
960 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
961 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
962 return MAKELONG( sizeXor, sizeXor );
966 /***********************************************************************
967 * CURSORICON_SetCursor
969 * Change the X cursor. Helper function for SetCursor() and ShowCursor().
970 * The Xlib critical section must be entered before calling this function.
972 static BOOL32 CURSORICON_SetCursor( HCURSOR16 hCursor )
974 Pixmap pixmapBits, pixmapMask, pixmapAll;
975 XColor fg, bg;
976 Cursor cursor = None;
978 if (!hCursor) /* Create an empty cursor */
980 static const char data[] = { 0 };
982 bg.red = bg.green = bg.blue = 0x0000;
983 pixmapBits = XCreateBitmapFromData( display, rootWindow, data, 1, 1 );
984 if (pixmapBits)
986 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
987 &bg, &bg, 0, 0 );
988 XFreePixmap( display, pixmapBits );
991 else /* Create the X cursor from the bits */
993 CURSORICONINFO *ptr;
994 XImage *image;
996 if (!(ptr = (CURSORICONINFO*)GlobalLock16( hCursor ))) return FALSE;
997 if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
999 WARN(cursor, "Cursor %04x has more than 1 bpp!\n", hCursor );
1000 return FALSE;
1003 /* Create a pixmap and transfer all the bits to it */
1005 /* NOTE: Following hack works, but only because XFree depth
1006 * 1 images really use 1 bit/pixel (and so the same layout
1007 * as the Windows cursor data). Perhaps use a more generic
1008 * algorithm here.
1010 pixmapAll = XCreatePixmap( display, rootWindow,
1011 ptr->nWidth, ptr->nHeight * 2, 1 );
1012 image = XCreateImage( display, DefaultVisualOfScreen(screen),
1013 1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
1014 ptr->nHeight * 2, 16, ptr->nWidthBytes);
1015 if (image)
1017 image->byte_order = MSBFirst;
1018 image->bitmap_bit_order = MSBFirst;
1019 image->bitmap_unit = 16;
1020 _XInitImageFuncPtrs(image);
1021 if (pixmapAll)
1022 XPutImage( display, pixmapAll, BITMAP_monoGC, image,
1023 0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
1024 image->data = NULL;
1025 XDestroyImage( image );
1028 /* Now create the 2 pixmaps for bits and mask */
1030 pixmapBits = XCreatePixmap( display, rootWindow,
1031 ptr->nWidth, ptr->nHeight, 1 );
1032 pixmapMask = XCreatePixmap( display, rootWindow,
1033 ptr->nWidth, ptr->nHeight, 1 );
1035 /* Make sure everything went OK so far */
1037 if (pixmapBits && pixmapMask && pixmapAll)
1039 /* We have to do some magic here, as cursors are not fully
1040 * compatible between Windows and X11. Under X11, there
1041 * are only 3 possible color cursor: black, white and
1042 * masked. So we map the 4th Windows color (invert the
1043 * bits on the screen) to black. This require some boolean
1044 * arithmetic:
1046 * Windows | X11
1047 * Xor And Result | Bits Mask Result
1048 * 0 0 black | 0 1 background
1049 * 0 1 no change | X 0 no change
1050 * 1 0 white | 1 1 foreground
1051 * 1 1 inverted | 0 1 background
1053 * which gives:
1054 * Bits = 'Xor' and not 'And'
1055 * Mask = 'Xor' or not 'And'
1057 * FIXME: apparently some servers do support 'inverted' color.
1058 * I don't know if it's correct per the X spec, but maybe
1059 * we ought to take advantage of it. -- AJ
1061 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1062 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1063 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1064 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
1065 XSetFunction( display, BITMAP_monoGC, GXandReverse );
1066 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
1067 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1068 XSetFunction( display, BITMAP_monoGC, GXorReverse );
1069 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
1070 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
1071 XSetFunction( display, BITMAP_monoGC, GXcopy );
1072 fg.red = fg.green = fg.blue = 0xffff;
1073 bg.red = bg.green = bg.blue = 0x0000;
1074 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
1075 &fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
1078 /* Now free everything */
1080 if (pixmapAll) XFreePixmap( display, pixmapAll );
1081 if (pixmapBits) XFreePixmap( display, pixmapBits );
1082 if (pixmapMask) XFreePixmap( display, pixmapMask );
1083 GlobalUnlock16( hCursor );
1086 if (cursor == None) return FALSE;
1087 if (CURSORICON_XCursor != None) XFreeCursor( display, CURSORICON_XCursor );
1088 CURSORICON_XCursor = cursor;
1090 if (rootWindow != DefaultRootWindow(display))
1092 /* Set the cursor on the desktop window */
1093 XDefineCursor( display, rootWindow, cursor );
1095 else
1097 /* Set the same cursor for all top-level windows */
1098 HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD );
1099 while(hwnd)
1101 Window win = WIN_GetXWindow( hwnd );
1102 if (win && win!=DefaultRootWindow(display))
1103 XDefineCursor( display, win, cursor );
1104 hwnd = GetWindow32( hwnd, GW_HWNDNEXT );
1107 return TRUE;
1111 /***********************************************************************
1112 * SetCursor16 (USER.69)
1114 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1116 return (HCURSOR16)SetCursor32( hCursor );
1120 /***********************************************************************
1121 * SetCursor32 (USER32.472)
1122 * RETURNS:
1123 * A handle to the previous cursor shape.
1125 HCURSOR32 WINAPI SetCursor32(
1126 HCURSOR32 hCursor /* Handle of cursor to show */
1128 HCURSOR32 hOldCursor;
1130 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1131 TRACE(cursor, "%04x\n", hCursor );
1132 hOldCursor = hActiveCursor;
1133 hActiveCursor = hCursor;
1134 /* Change the cursor shape only if it is visible */
1135 if (CURSOR_ShowCount >= 0)
1137 EnterCriticalSection( &X11DRV_CritSection );
1138 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1139 LeaveCriticalSection( &X11DRV_CritSection );
1141 return hOldCursor;
1145 /***********************************************************************
1146 * SetCursorPos16 (USER.70)
1148 void WINAPI SetCursorPos16( INT16 x, INT16 y )
1150 SetCursorPos32( x, y );
1154 /***********************************************************************
1155 * SetCursorPos32 (USER32.474)
1157 BOOL32 WINAPI SetCursorPos32( INT32 x, INT32 y )
1159 TRACE(cursor, "x=%d y=%d\n", x, y );
1160 TSXWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, x, y );
1161 return TRUE;
1165 /***********************************************************************
1166 * ShowCursor16 (USER.71)
1168 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1170 return ShowCursor32( bShow );
1174 /***********************************************************************
1175 * ShowCursor32 (USER32.530)
1177 INT32 WINAPI ShowCursor32( BOOL32 bShow )
1179 TRACE(cursor, "%d, count=%d\n",
1180 bShow, CURSOR_ShowCount );
1182 EnterCriticalSection( &X11DRV_CritSection );
1183 if (bShow)
1185 if (++CURSOR_ShowCount == 0) /* Show it */
1186 CALL_LARGE_STACK( CURSORICON_SetCursor, hActiveCursor );
1188 else
1190 if (--CURSOR_ShowCount == -1) /* Hide it */
1191 CALL_LARGE_STACK( CURSORICON_SetCursor, 0 );
1193 LeaveCriticalSection( &X11DRV_CritSection );
1194 return CURSOR_ShowCount;
1198 /***********************************************************************
1199 * GetCursor16 (USER.247)
1201 HCURSOR16 WINAPI GetCursor16(void)
1203 return hActiveCursor;
1207 /***********************************************************************
1208 * GetCursor32 (USER32.227)
1210 HCURSOR32 WINAPI GetCursor32(void)
1212 return hActiveCursor;
1216 /***********************************************************************
1217 * ClipCursor16 (USER.16)
1219 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1221 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1222 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1223 return TRUE;
1227 /***********************************************************************
1228 * ClipCursor32 (USER32.53)
1230 BOOL32 WINAPI ClipCursor32( const RECT32 *rect )
1232 if (!rect) SetRectEmpty32( &CURSOR_ClipRect );
1233 else CopyRect32( &CURSOR_ClipRect, rect );
1234 return TRUE;
1238 /***********************************************************************
1239 * GetCursorPos16 (USER.17)
1241 void WINAPI GetCursorPos16( POINT16 *pt )
1243 Window root, child;
1244 int rootX, rootY, childX, childY;
1245 unsigned int mousebut;
1247 if (!pt) return;
1248 if (!TSXQueryPointer( display, rootWindow, &root, &child,
1249 &rootX, &rootY, &childX, &childY, &mousebut ))
1250 pt->x = pt->y = 0;
1251 else
1253 pt->x = childX;
1254 pt->y = childY;
1255 if (mousebut & Button1Mask)
1256 AsyncMouseButtonsStates[0] = MouseButtonsStates[0] = TRUE;
1257 else
1258 MouseButtonsStates[0] = FALSE;
1259 if (mousebut & Button2Mask)
1260 AsyncMouseButtonsStates[1] = MouseButtonsStates[1] = TRUE;
1261 else
1262 MouseButtonsStates[1] = FALSE;
1263 if (mousebut & Button3Mask)
1264 AsyncMouseButtonsStates[2] = MouseButtonsStates[2] = TRUE;
1265 else
1266 MouseButtonsStates[2] = FALSE;
1268 TRACE(cursor, "ret=%d,%d\n", pt->x, pt->y );
1272 /***********************************************************************
1273 * GetCursorPos32 (USER32.229)
1275 void WINAPI GetCursorPos32( POINT32 *pt )
1277 POINT16 pt16;
1278 GetCursorPos16( &pt16 );
1279 if (pt) CONV_POINT16TO32( &pt16, pt );
1283 /***********************************************************************
1284 * GetClipCursor16 (USER.309)
1286 void WINAPI GetClipCursor16( RECT16 *rect )
1288 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1292 /***********************************************************************
1293 * GetClipCursor32 (USER32.221)
1295 void WINAPI GetClipCursor32( RECT32 *rect )
1297 if (rect) CopyRect32( rect, &CURSOR_ClipRect );
1300 /**********************************************************************
1301 * LookupIconIdFromDirectoryEx16 (USER.364)
1303 * FIXME: exact parameter sizes
1305 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1306 INT16 width, INT16 height, UINT16 cFlag )
1308 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1309 UINT16 retVal = 0;
1310 if( dir && !dir->idReserved && (dir->idType & 3) )
1312 int colors = (cFlag == LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
1313 if( bIcon )
1315 ICONDIRENTRY* entry;
1316 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1317 if( entry ) retVal = entry->wResId;
1319 else
1321 CURSORDIRENTRY* entry;
1322 entry = CURSORICON_FindBestCursor( dir, width, height );
1323 if( entry ) retVal = entry->wResId;
1326 else WARN(cursor, "invalid resource directory\n");
1327 return retVal;
1330 /**********************************************************************
1331 * LookupIconIdFromDirectoryEx32 (USER32.380)
1333 INT32 WINAPI LookupIconIdFromDirectoryEx32( LPBYTE dir, BOOL32 bIcon,
1334 INT32 width, INT32 height, UINT32 cFlag )
1336 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1339 /**********************************************************************
1340 * LookupIconIdFromDirectory (USER.???)
1342 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1344 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1345 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1346 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1349 /**********************************************************************
1350 * LookupIconIdFromDirectory (USER32.379)
1352 INT32 WINAPI LookupIconIdFromDirectory32( LPBYTE dir, BOOL32 bIcon )
1354 return LookupIconIdFromDirectoryEx32( dir, bIcon,
1355 bIcon ? SYSMETRICS_CXICON : SYSMETRICS_CXCURSOR,
1356 bIcon ? SYSMETRICS_CYICON : SYSMETRICS_CYCURSOR, bIcon ? 0 : LR_MONOCHROME );
1359 /**********************************************************************
1360 * GetIconID (USER.455)
1362 WORD WINAPI GetIconID( HGLOBAL16 hResource, DWORD resType )
1364 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1366 TRACE(cursor, "hRes=%04x, entries=%i\n",
1367 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1369 switch(resType)
1371 case RT_CURSOR16:
1372 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1373 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1374 case RT_ICON16:
1375 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1376 SYSMETRICS_CXICON, SYSMETRICS_CYICON, 0 );
1377 default:
1378 WARN(cursor, "invalid res type %ld\n", resType );
1380 return 0;
1383 /**********************************************************************
1384 * LoadCursorIconHandler (USER.336)
1386 * Supposed to load resources of Windows 2.x applications.
1388 HGLOBAL16 WINAPI LoadCursorIconHandler( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1390 FIXME(cursor,"(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1391 hResource, hModule, hRsrc);
1392 return (HGLOBAL16)0;
1395 /**********************************************************************
1396 * LoadDIBIconHandler (USER.357)
1398 * RT_ICON resource loader, installed by USER_SignalProc when module
1399 * is initialized.
1401 HGLOBAL16 WINAPI LoadDIBIconHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1403 /* If hResource is zero we must allocate a new memory block, if it's
1404 * non-zero but GlobalLock() returns NULL then it was discarded and
1405 * we have to recommit some memory, otherwise we just need to check
1406 * the block size. See LoadProc() in 16-bit SDK for more.
1409 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1410 if( hMemObj )
1412 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1413 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1414 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1415 SYSMETRICS_CXICON, SYSMETRICS_CYICON, LR_DEFAULTCOLOR );
1417 return hMemObj;
1420 /**********************************************************************
1421 * LoadDIBCursorHandler (USER.356)
1423 * RT_CURSOR resource loader. Same as above.
1425 HGLOBAL16 WINAPI LoadDIBCursorHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1427 hMemObj = USER_CallDefaultRsrcHandler( hMemObj, hModule, hRsrc );
1428 if( hMemObj )
1430 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1431 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1432 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1433 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, LR_MONOCHROME );
1435 return hMemObj;
1438 /**********************************************************************
1439 * LoadIconHandler (USER.456)
1441 HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
1443 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1445 TRACE(cursor,"hRes=%04x\n",hResource);
1447 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1448 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1451 /***********************************************************************
1452 * LoadCursorW (USER32.362)
1454 HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
1456 return CURSORICON_Load32( hInstance, name,
1457 SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE);
1460 /***********************************************************************
1461 * LoadCursorA (USER32.359)
1463 HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
1465 HCURSOR32 res=0;
1466 if(!HIWORD(name))
1467 return LoadCursor32W(hInstance,(LPCWSTR)name);
1468 else
1470 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1471 res = LoadCursor32W(hInstance, uni);
1472 HeapFree( GetProcessHeap(), 0, uni);
1474 return res;
1477 /***********************************************************************
1478 * LoadIconW (USER32.364)
1480 HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
1482 return CURSORICON_Load32( hInstance, name,
1483 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
1484 MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE );
1487 /***********************************************************************
1488 * LoadIconA (USER32.363)
1490 HICON32 WINAPI LoadIcon32A(HINSTANCE32 hInstance, LPCSTR name)
1492 HICON32 res=0;
1494 if( !HIWORD(name) )
1495 return LoadIcon32W(hInstance, (LPCWSTR)name);
1496 else
1498 LPWSTR uni = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
1499 res = LoadIcon32W( hInstance, uni );
1500 HeapFree( GetProcessHeap(), 0, uni );
1502 return res;
1505 /**********************************************************************
1506 * GetIconInfo (USER32.242)
1508 BOOL32 WINAPI GetIconInfo(HICON32 hIcon,LPICONINFO iconinfo) {
1509 CURSORICONINFO *ciconinfo;
1511 ciconinfo = GlobalLock16(hIcon);
1512 if (!ciconinfo)
1513 return FALSE;
1514 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1515 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1516 iconinfo->fIcon = TRUE; /* hmm */
1517 /* FIXME ... add both bitmaps */
1518 return TRUE;
1521 /**********************************************************************
1522 * CreateIconIndirect (USER32.78)
1524 HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
1525 BITMAPOBJ *bmpXor,*bmpAnd;
1526 HICON32 hObj;
1527 int sizeXor,sizeAnd;
1529 bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmColor, BITMAP_MAGIC );
1530 bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( iconinfo->hbmMask, BITMAP_MAGIC );
1532 sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
1533 sizeAnd = bmpAnd->bitmap.bmHeight * bmpAnd->bitmap.bmWidthBytes;
1535 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1536 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1537 if (hObj)
1539 CURSORICONINFO *info;
1541 info = (CURSORICONINFO *)GlobalLock16( hObj );
1542 info->ptHotSpot.x = iconinfo->xHotspot;
1543 info->ptHotSpot.y = iconinfo->yHotspot;
1544 info->nWidth = bmpXor->bitmap.bmWidth;
1545 info->nHeight = bmpXor->bitmap.bmHeight;
1546 info->nWidthBytes = bmpXor->bitmap.bmWidthBytes;
1547 info->bPlanes = bmpXor->bitmap.bmPlanes;
1548 info->bBitsPerPixel = bmpXor->bitmap.bmBitsPixel;
1550 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1552 GetBitmapBits32( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1553 GetBitmapBits32( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1554 GlobalUnlock16( hObj );
1556 return hObj;
1560 /**********************************************************************
1561 * DrawIconEx16 (USER.394)
1563 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1564 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1565 HBRUSH16 hbr, UINT16 flags)
1567 return DrawIconEx32(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1568 istep, hbr, flags);
1572 /******************************************************************************
1573 * DrawIconEx32 [USER32.160] Draws an icon or cursor on device context
1575 * NOTES
1576 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1578 * PARAMS
1579 * hdc [I] Handle to device context
1580 * x0 [I] X coordinate of upper left corner
1581 * y0 [I] Y coordinate of upper left corner
1582 * hIcon [I] Handle to icon to draw
1583 * cxWidth [I] Width of icon
1584 * cyWidth [I] Height of icon
1585 * istep [I] Index of frame in animated cursor
1586 * hbr [I] Handle to background brush
1587 * flags [I] Icon-drawing flags
1589 * RETURNS
1590 * Success: TRUE
1591 * Failure: FALSE
1593 BOOL32 WINAPI DrawIconEx32( HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
1594 INT32 cxWidth, INT32 cyWidth, UINT32 istep,
1595 HBRUSH32 hbr, UINT32 flags )
1597 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1598 HDC32 hMemDC = CreateCompatibleDC32 (hdc);
1599 BOOL32 result = FALSE;
1601 if (istep)
1602 FIXME(icon, "Ignoring istep=%d\n", istep);
1603 if (hbr)
1604 FIXME(icon, "Ignoring hbr=%x\n", hbr);
1605 if (flags & DI_COMPAT)
1606 FIXME(icon, "Ignoring flag DI_COMPAT\n");
1608 if (hMemDC && ptr)
1610 HBITMAP32 hXorBits, hAndBits;
1611 COLORREF oldFg, oldBg;
1613 /* Calculate the size of the destination image. */
1614 if (cxWidth == 0)
1615 if (flags & DI_DEFAULTSIZE)
1616 cxWidth = GetSystemMetrics32 (SM_CXICON);
1617 else
1618 cxWidth = ptr->nWidth;
1619 if (cyWidth == 0)
1620 if (flags & DI_DEFAULTSIZE)
1621 cyWidth = GetSystemMetrics32 (SM_CYICON);
1622 else
1623 cyWidth = ptr->nHeight;
1625 hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
1626 ptr->bPlanes, ptr->bBitsPerPixel,
1627 (char *)(ptr + 1)
1628 + ptr->nHeight *
1629 BITMAP_WIDTH_BYTES(ptr->nWidth,1) );
1630 hAndBits = CreateBitmap32 ( cxWidth, cyWidth,
1631 1, 1, (char *)(ptr+1) );
1632 oldFg = SetTextColor32( hdc, RGB(0,0,0) );
1633 oldBg = SetBkColor32( hdc, RGB(255,255,255) );
1635 if (hXorBits && hAndBits)
1637 HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
1638 if (flags & DI_MASK)
1639 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1640 hMemDC, 0, 0, SRCAND);
1641 SelectObject32( hMemDC, hXorBits );
1642 if (flags & DI_IMAGE)
1643 BitBlt32 (hdc, x0, y0, cxWidth, cyWidth,
1644 hMemDC, 0, 0, SRCPAINT);
1645 SelectObject32( hMemDC, hBitTemp );
1646 result = TRUE;
1649 SetTextColor32( hdc, oldFg );
1650 SetBkColor32( hdc, oldBg );
1651 if (hXorBits) DeleteObject32( hXorBits );
1652 if (hAndBits) DeleteObject32( hAndBits );
1654 if (hMemDC) DeleteDC32( hMemDC );
1655 GlobalUnlock16( hIcon );
1656 return result;